public interface Service
When the application starts, all services in the server registry will be notified. Similarly when the application stops.
import ratpack.server.RatpackServer;
import ratpack.server.ServerConfig;
import ratpack.server.Service;
import ratpack.server.StartEvent;
import ratpack.server.StopEvent;
import java.util.List;
import java.util.LinkedList;
import static org.junit.Assert.*;
public class Example {
static class RecordingService implements Service {
public final List<String> events = new LinkedList<>();
public void onStart(StartEvent event) {
events.add("start");
}
public void onStop(StopEvent event) {
events.add("stop");
}
}
public static void main(String... args) throws Exception {
RecordingService service = new RecordingService();
RatpackServer server = RatpackServer.of(s -> s
.serverConfig(ServerConfig.embedded())
.registryOf(r -> r.add(service))
.handler(r -> ctx -> ctx.render("ok"))
);
assertEquals("[]", service.events.toString());
server.start();
assertEquals("[start]", service.events.toString());
server.reload();
assertEquals("[start, stop, start]", service.events.toString());
server.stop();
assertEquals("[start, stop, start, stop]", service.events.toString());
}
}
Services are notified of start events in the order returned by the Registry.getAll(java.lang.Class<O>)
method.
They are notified in reverse order for stop events.
The order in that services are returned from the server registry is dependent on the registry implementation.
Generally, most implementations return objects in the order in which they are added to the registry.
The onStart(ratpack.server.StartEvent)
and onStop(ratpack.server.StopEvent)
methods are always executed within a distinct Execution
, for each service.
This means that implementations of these methods are free to perform async ops (e.g. use the HttpClient
, or block
).
import ratpack.server.RatpackServer;
import ratpack.server.ServerConfig;
import ratpack.server.Service;
import ratpack.server.StartEvent;
import ratpack.server.StopEvent;
import java.util.List;
import java.util.LinkedList;
import static org.junit.Assert.*;
public class Example {
static class RecordingService implements Service {
public final List<String> events = new LinkedList<>();
public void onStart(StartEvent event) {
event.getExecControl().promiseOf("start").map(String::toUpperCase).then(events::add);
}
public void onStop(StopEvent event) {
event.getExecControl().promiseOf("stop").map(String::toUpperCase).then(events::add);
}
}
public static void main(String... args) throws Exception {
RecordingService service = new RecordingService();
RatpackServer server = RatpackServer.of(s -> s
.serverConfig(ServerConfig.embedded())
.registryOf(r -> r.add(service))
.handler(r -> ctx -> ctx.render("ok"))
);
server.start();
assertEquals("[START]", service.events.toString());
server.stop();
assertEquals("[START, STOP]", service.events.toString());
}
}
There is no need to catch promise errors. An error handler for the execution is installed that effectively treats any exceptions as if they were thrown by the method.
This interface does need to be used for business-logic type services, unless such services need to participate in the application lifecycle.
Even in such a case, it is generally better to decouple the business-logic type service from Ratpack (i.e. this interface) and have a
Service
implementation that drives the business-logic service.
The event objects given to the start/stop methods provide access to the server registry. This can be used, for example, to get hold of a database connection that was added to the server registry as part of the server definition.
Alternatively, when using the Guice support the service can be injected by Guice.
import ratpack.server.RatpackServer;
import ratpack.server.ServerConfig;
import ratpack.server.Service;
import ratpack.server.StartEvent;
import ratpack.server.StopEvent;
import ratpack.guice.Guice;
import ratpack.util.Types;
import javax.inject.Inject;
import java.util.List;
import java.util.LinkedList;
import static org.junit.Assert.*;
public class Example {
static class RecordingService implements Service {
public final List<String> events;
@Inject
public RecordingService(List<String> events) {
this.events = events;
}
public void onStart(StartEvent event) {
events.add("start");
}
public void onStop(StopEvent event) {
events.add("stop");
}
}
public static void main(String... args) throws Exception {
List<String> list = new LinkedList<>();
RatpackServer server = RatpackServer.of(s -> s
.serverConfig(ServerConfig.embedded())
.registry(Guice.registry(b -> b
.bindInstance(Types.listOf(String.class), list)
.bind(RecordingService.class)
))
.handler(r -> ctx -> ctx.render("ok"))
);
server.start();
assertEquals("[start]", list.toString());
server.stop();
assertEquals("[start, stop]", list.toString());
}
}
If an onStart
method errors, it will prevent the “application� from launching.
In development mode
, the application will start and display the error page for all requests with the error.
When not in development mode, the exception will be thrown from the RatpackServer.start()
method.
If starting the app in a “main method�, this will prevent the JVM from starting.
If an onStop
method errors, the error will be logged and then the next service invoked.
That is, a failed onStop
method is not considered fatal.
When a startup failure occurs, the server effectively shuts down which includes executing all the onStop
methods.
Modifier and Type | Method and Description |
---|---|
default String |
getName()
The name of this service, used for display purposes.
|
default void |
onStart(StartEvent event)
Server startup event.
|
default void |
onStop(StopEvent event)
Server stop event.
|
default String getName()
The default implementation is to return getClass().getName()
.
@NonBlocking default void onStart(StartEvent event) throws Exception
event
- meta information about the startup eventException
- any@NonBlocking default void onStop(StopEvent event) throws Exception
event
- meta information about the stop eventException
- any