Understanding Hello World

§Understanding Hello World

After creating and running Hello World from the command line, you no doubt appreciate what Lagom framework did for you. There was no need to determine what infrastructure you might need and then install and configure it. The template removed the necessity to set up a project or build structure. And, as you create services of your own, Lagom detects changes and performs a hot reload! Lagom allows you to concentrate on satisfying your business needs.

The separation of concerns illustrated in Hello World and an introduction to service descriptors and the registry will help you as you start developing your own microservices:

§Service interface

The source file defining a service interface belongs in the service’s api project. For example, in Hello World, HelloService.java, the source file for the hello service interface resides in the hello-api directory of the Maven project or sbt build.

public interface HelloService extends Service {

  ServiceCall<NotUsed, String> hello(String id);

  ServiceCall<GreetingMessage, Done> useGreeting(String id);

  @Override
  default Descriptor descriptor() {
    return named("helloservice")
        .withCalls(
            restCall(Method.GET, "/api/hello/:id", this::hello),
            pathCall("/api/hello/:id", this::useGreeting))
        .withAutoAcl(true);
  }
}

Note that:

  • The service interface inherits from Service and provides an implementation of Service.descriptor method.

  • The implementation of Service.descriptor returns a Descriptor. The HelloService descriptor defines the service name and the REST endpoints it offers. For each endpoint, declare an abstract method in the service interface, as illustrated in the HelloService.hello method. For more information, see Service Descriptors.

§Service implementation

The related impl directory contains the implementation of the service interface’s abstract methods. For instance, HelloServiceImpl.java in the hello-impl directory implements the hello service HelloService.hello method. The service implementation uses a sharded, persistent, typed actor providing data persistence using Event Sourcing and CQRS.

public class HelloServiceImpl implements HelloService {

  private final Duration askTimeout = Duration.ofSeconds(5);
  private ClusterSharding clusterSharding;

  @Inject
  public HelloServiceImpl(ClusterSharding clusterSharding) {
    this.clusterSharding = clusterSharding;
  }

  @Override
  public ServiceCall<NotUsed, String> hello(String id) {
    return request -> {
      EntityRef<HelloCommand> ref =
          clusterSharding.entityRefFor(HelloAggregate.ENTITY_TYPE_KEY, id);
      return ref.<HelloCommand.Greeting>ask(replyTo -> new Hello(id, replyTo), askTimeout)
          .thenApply(greeting -> greeting.message);
    };
  }

  @Override
  public ServiceCall<GreetingMessage, Done> useGreeting(String id) {
    return request -> {
      EntityRef<HelloCommand> ref =
          clusterSharding.entityRefFor(HelloAggregate.ENTITY_TYPE_KEY, id);
      return ref.<HelloCommand.Confirmation>ask(
              replyTo -> new UseGreetingMessage(request.message, replyTo), askTimeout)
          .thenApply(
              confirmation -> {
                if (confirmation instanceof HelloCommand.Accepted) {
                  return Done.getInstance();
                } else {
                  throw new BadRequest(((HelloCommand.Rejected) confirmation).reason);
                }
              });
    };
  }
}

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.