Getting started with Lagom in Maven

§Getting started with Lagom in Maven

This page shows how to create and run your first Lagom project.

§Creating a new Lagom project

A Lagom system is typically made up of a set of maven projects, each build providing multiple services. The easiest way to get started with a new Lagom system is to create a new project using the Maven archetype plugin, with the Lagom Maven archetype:

$ mvn archetype:generate -DarchetypeGroupId=com.lightbend.lagom \
  -DarchetypeArtifactId=maven-archetype-lagom-java -DarchetypeVersion=1.1.0

Note: Ensure you replace the 1.1.0 archetype version with the latest version of Lagom.

This will prompt you for a groupId, artifactId and version. You might choose, for example, com.example as a groupId, and my-first-system for an artifactId. Once you’ve followed the prompts, it will create a new system with two services in it: hello and stream.

§Anatomy of a Lagom project

The created project contains the following elements:

my-first-system          → Project root
 └ hello-api             → hello world api project
 └ hello-impl            → hello world implementation project
 └ stream-api            → stream api project
 └ stream-impl           → stream implementation project
 └ integration-tests     → Integration tests
 └ pom.xml               → Project root 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.

§Understanding services projects

  • The service interface is always placed in the api project. For instance, the service interface for the hello service can be found in the hello-api project (look for the HelloService.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 of Service#descriptor method.

  • The implementation of Service#descriptor returns a Descriptor. A Descriptor 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 the HelloService#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 the hello service, can be found in the hello-impl project (look for the HelloServiceImpl.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()));
    };
  }
}

§Running Lagom services

Lagom includes a development environment that let you start all your services by invoking the runAll task on the Lagom maven plugin. Open the terminal and cd to your Lagom project (some log output cut for brevity):

$ cd my-first-system
$ mvn lagom: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, press enter to stop and go back to the console...)

You can verify that the services are indeed up and running by invoking 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.

Found an error in this documentation? The source code for this page can be found here. Please feel free to edit and contribute a pull request.