§Getting started with Lagom in sbt
This page shows how to create and run your first Lagom project using sbt.
§Creating a new Lagom project
A Lagom system is typically made up of a set of sbt builds, each build providing multiple services. The easiest way to get started with a new Lagom system is to create a new project using the lagom
Activator template:
$ activator new my-first-system lagom-java
This will create a new system with two services in it: helloworld
and hellostream
.
§Anatomy of a Lagom project
The created project contains the following elements:
my-first-system → Project root
└ hellostream-api → hellostream api project
└ hellostream-impl → hellostream implementation project
└ helloworld-api → helloworld api project
└ helloworld-impl → helloworld implementation project
└ project → sbt configuration files
└ build.properties → Marker for sbt project
└ plugins.sbt → sbt plugins including the declaration for Lagom itself
└ build.sbt → Your project build file
- Notice how each service is broken up into two projects: api and implementation. The api project contains a service interface through which consumers may interact with the service. While the implementation project contains the actual service implementation.
- The
project
folder contains sbt specific files. - The
build.sbt
file, which contains all information necessary to build, run, and deploy your services.
§Understanding services projects
- The service interface is always placed in the api project. For instance, the service interface for the
helloworld
service can be found in thehelloworld-api
project (look for theHelloService.java
source file).
public interface HelloService extends Service {
ServiceCall<NotUsed, String> hello(String id);
@Override
default Descriptor descriptor() {
return named("helloservice").withCalls(
restCall(Method.GET, "/api/hello/:id", this::hello)
).withAutoAcl(true);
}
}
-
The service interface needs to inherit from
Service
and provide an implementation ofService#descriptor
method. -
The implementation of
Service#descriptor
returns aDescriptor
. ADescriptor
defines the service name and the REST endpoints offered by a service. For each declared endpoint, an abstract method is declared in the service interface, e.g., see theHelloService#hello
method. -
The implementation of the service abstract methods is provided by the related implementation project. For instance, the service implementation of the
HelloService#hello
method, for thehelloworld
service, can be found in thehelloworld-impl
project (look for theHelloServiceImpl.java
source file).
public class HelloServiceImpl implements HelloService {
private final PersistentEntityRegistry persistentEntityRegistry;
@Inject
public HelloServiceImpl(PersistentEntityRegistry persistentEntityRegistry) {
this.persistentEntityRegistry = persistentEntityRegistry;
persistentEntityRegistry.register(HelloWorld.class);
}
@Override
public ServiceCall<NotUsed, String> hello(String id) {
return request -> {
// Look up the hello world entity for the given ID.
PersistentEntityRef<HelloCommand> ref = persistentEntityRegistry.refFor(HelloWorld.class, id);
// Ask the entity the Hello command.
return ref.ask(new Hello(id, Optional.empty()));
};
}
}
- The
PersistentEntityRegistry
allows to persist data in the database using Event Sourcing and CQRS.
§Running Lagom services
Lagom includes a development environment that let you start all your services by simply typing runAll
in the activator console. Open the terminal and cd
to your Lagom project:
$ cd my-first-system
$ activator
... (booting up)
> runAll
[info] Starting embedded Cassandra server
..........
[info] Cassandra server running at 127.0.0.1:4000
[info] Service locator is running at http://localhost:8000
[info] Service gateway is running at http://localhost:9000
[info] Service helloworld-impl listening for HTTP on 0:0:0:0:0:0:0:0:24266
[info] Service hellostream-impl listening for HTTP on 0:0:0:0:0:0:0:0:26230
(Services started, use Ctrl+D to stop and go back to the console...)
You can verify that the services are indeed up and running by exercising one of its endpoints, e.g:
$ curl http://localhost:9000/api/hello/World
And you should get back the message Hello, World!
.
If you are wondering why we have created two services in the seed template, instead of having just one, the reason is simply that (quoting Jonas Bonér):
One microservice is no microservice - they come in systems.
Said otherwise, we believe you will be creating several services, and we felt it was important to showcase intra-service communication.