§Additional Routers
Since Lagom 1.5.0, it is possible to extend a Lagom Service with additional Play Routers.
This is particularly useful when integrating Lagom with existing Play Routers, for instance a Play gRPC Router, or any other Play router that you have at your disposal.
You add an additional router when binding your Lagom Service in your Guice module. You should pass the additional routers to the bindService
method together with the Service interface and its implementation. You do this by means of a helper method called additionalRouters
.
There are two variants for additionalRouters
, one that receives a Class<play.api.routing.Router>
and one that receives an instance of play.api.routing.Router
.
The first one should be used when your Router has some dependencies and needs to get them injected by Lagom’s runtime DI infrastructure (Guice). In this case, you pass the class and Guice will initialize it with the right dependencies.
public class HelloWorldModule extends AbstractModule implements ServiceGuiceSupport {
@Override
protected void configure() {
bindService(
HelloService.class, HelloServiceImpl.class, additionalRouter(SomePlayRouter.class));
}
}
The second variant should be used when the Router does not have any other dependencies and therefore can be immediately passed as an instance.
public class HelloWorldModule extends AbstractModule implements ServiceGuiceSupport {
@Override
protected void configure() {
bindService(
HelloService.class, HelloServiceImpl.class, additionalRouter(new SomePlayRouter()));
}
}
§File Upload Example
The following example shows how you can add a file upload endpoint to an existing Lagom Service.
The example is based on JavaRoutingDsl that allows you to build a Play Router programmatically. It adds an extra path (/api/files
) that receives POST calls for multipart-form data.
class FileUploadRouter implements SimpleRouter {
private final Router delegate;
@Inject
public FileUploadRouter(RoutingDsl routingDsl) {
this.delegate =
routingDsl
.POST("/api/files")
.routingTo(
request -> {
Http.MultipartFormData<File> body = request.body().asMultipartFormData();
String response =
body.getFiles().stream()
.map(f -> f.getRef().getAbsolutePath())
.collect(joining(",", "Uploaded[", "]"));
return ok(response);
})
.build()
.asScala();
}
@Override
public PartialFunction<RequestHeader, Handler> routes() {
return delegate.routes();
}
}
In your Guice module, you append the additional router when binding your Lagom service.
public class HelloWorldModule extends AbstractModule implements ServiceGuiceSupport {
@Override
protected void configure() {
bindService(
HelloService.class, HelloServiceImpl.class, additionalRouter(FileUploadRouter.class));
}
}
The path /api/files
will now be available on your Lagom service:
curl -X POST -F "[email protected]" -v http://localhost:65499/api/files
Note that in that example we are not using the Service Gateway to access the application. We are calling it directly using the service port, in this case,
65499
.
§Service Gateway Considerations
An additional router is not part of your application ServiceDescriptor
and therefore can’t be automatically published as endpoints to the Service Gateway in development mode.
If you want to access your additional routers through the gateway, you will need to explicitly add the ACL (Access Control List) for it in your ServiceDescriptor
definition.
interface HelloWordService extends Service {
ServiceCall<NotUsed, String> hello(String name);
@Override
default Descriptor descriptor() {
return named("fileupload")
.withCalls(pathCall("/api/hello/:name", this::hello))
.withAutoAcl(true)
.withServiceAcls(path("/api/files"));
}
}
Once the path is published on the Service Gateway, you can call:
curl -X POST -F "[email protected]" -v http://localhost:9000/api/files
Note usage of port 9000 (Lagom’s Dev Mode ServiceGateway)
§Lagom Client Considerations
Additional routers are not part of the Service API and therefore are not accessible from generated Lagom clients. Lagom clients only have access to methods defined on the Service interface.
Additional routers are only part of the exposed HTTP endpoints. To access then, you will need to use an HTTP client, eg: Play-WS