Integrating with non Lagom services

§Integrating with non Lagom services

§Invoking Lagom services

Lagom service calls are implemented using idiomatic REST. The simplest way to invoke a Lagom service from another framework is to use that frameworks REST client to invoke the Lagom service.

Another way to invoke Lagom services, if the client is running in a JVM, is to use the Lagom service interface directly.

§Using the Lagom service client

§Configuring dependencies

To use the Lagom service interface, you will need to add a dependency on the Lagom client to your build. If using sbt, this can be done by adding the following dependency:

libraryDependencies += lagomScaladslClient

Of course, you will also need to add a dependency to the API project that you have created in your Lagom project. For more details, see Understanding your project structure.

§Creating a LagomClientFactory

In a LagomApplication you can create clients by calling the serviceClient method. In non Lagom applications you need to first to create a LagomClientFactory. This factory will give you access to an equivalent serviceClient method to generate clients.

A LagomClientFactory needs an ActorSystem and Akka Streams Materializer and therefore there are two ways of creating it depending if your application is already using Akka or not. You can create it by extending one of the following abstract classes: LagomClientFactory or StandaloneLagomClientFactory.

In both cases, the constructor takes two arguments, a service name and a ClassLoader. The service name, will be the name of the client service that is consuming the remote Lagom service, and will impact how calls made through clients generated by this factory will identify themselves. The second argument is a ClassLoader, it will be used to create the service proxy and needs to have the API for the client in it.

There is one more component that you’ll need to provide when creating a LagomClientFactory, that is a service locator. It is up to you what service locator you use, it could be a third party service locator, or a service locator created from static configuration.

Lagom provides a number of built-in service locators, including a StaticServiceLocator, a RoundRobinServiceLocator and a ConfigurationServiceLocator. The easiest way to use these is to mix in their respective `Components` traits.

The StandaloneLagomClientFactory variant is useful for applications that do not have a running ActorSystem. Internally, the StandaloneLagomClientFactory will create a dedicated ActorSystem and Materializer to be used by the clients. Both will be managed by the StandaloneLagomClientFactory and will be shutdown when the factory is closed.

For example, here’s a StandaloneLagomClientFactory built using the static service locator, which uses a static URI:

import java.net.URI
import com.lightbend.lagom.scaladsl.client._
import play.api.libs.ws.ahc.AhcWSComponents

val clientFactory =
  new StandaloneLagomClientFactory("my-client", classOf[StandaloneLagomClientFactory].getClassLoader)
    with StaticServiceLocatorComponents
    with AhcWSComponents {
    override def staticServiceUri = URI.create("http://localhost:8080")
  }

We highly recommend you to not use StandaloneLagomClientFactory if your application has already an ActorSystem. The reason for that is that the factory will start its own ActorSystem and will read the same configuration as your default ActorSystem. This can cause a few unexpected errors, for instances, you may get port binding conflicts when both Actor Systems try to bind the akka-remote port.

The LagomClientFactory variant is useful for applications that have a running ActorSystem. In which case, we recommend to reuse the existing ActorSystem and Materializer.

The easiest way to reuse your existing ActorSystem and Akka Stream Materializer is to extend the LagomClientFactory and add a constructor where you can pass them as arguments.

For example, here’s a LagomClientFactory built using the static service locator, which uses a static URI, and reusing an ActorSystem and Materializer created outside it:

import java.net.URI
import com.lightbend.lagom.scaladsl.client._
import play.api.libs.ws.ahc.AhcWSComponents

class MyLagomClientFactory(val actorSystem: ActorSystem, val materializer: Materializer)
    extends LagomClientFactory("my-client", classOf[MyLagomClientFactory].getClassLoader)
    with StaticServiceLocatorComponents
    with AhcWSComponents {
  override def staticServiceUri = URI.create("http://localhost:8080")
}

val actorSystem   = ActorSystem("my-app")
val materializer  = Materializer.matFromSystem(actorSystem)
val clientFactory = new MyLagomClientFactory(actorSystem, materializer)

When you have finished with the application, for example, when the system shuts down, you need to stop the factory, by invoking the stop() method:

clientFactory.stop()

You may want to override the stop() method when implementing your own LagomClientFactory. For instance, in case you are reusing an existing ActorSystem, but prefer to use a internal Materializer. In which case, you can use this method to shutdown the Materializer only. When overriding this method, make sure you also release the internally managed resources by calling LagomClientFactory.releaseInternalResources() method.

Typically this factory will be a singleton in your system. If your system is using Spring for example, you would create a FactoryBean that instantiates it, and you would implement a @PreDestroy annotated method that stopped the factory client.

§Creating a client

Once you have created the factory client, you can easily create a client using it, for example:

val helloService = clientFactory.serviceClient.implement[HelloService]

Here we’ve created a client for the HelloService the same way we would in a regular Lagom application, using serviceClient.implementClient.

§Working with dev mode

When running your service in development, you can tell the service to use Lagom’s dev mode service locator, by adding a dependency on Lagom’s dev mode support:

libraryDependencies += lagomScaladslDevMode

Then, when you instantiate your factory client, rather than mixing in your production service locator, you can mix in the LagomDevModeServiceLocatorComponents trait to get the dev mode service locator:

import java.net.URI
import com.lightbend.lagom.scaladsl.client._
import play.api.libs.ws.ahc.AhcWSComponents
import com.lightbend.lagom.scaladsl.devmode.LagomDevModeServiceLocatorComponents

val clientApplication = if (devMode) {
  new StandaloneLagomClientFactory("my-client") with AhcWSComponents with LagomDevModeServiceLocatorComponents
} else {
  new StandaloneLagomClientFactory("my-client") with StaticServiceLocatorComponents with AhcWSComponents {
    override def staticServiceUri = URI.create("http://localhost:8080")
  }
}

You’ll also need to configure your application to tell it where the service locator is running, this can be done by passing a system property to your application when it starts up, for example:

-Dlagom.service-locator-url=http://localhost:9008

Alternatively, you can configure it programmatically by overriding the devModeServiceLocatorUrl value on the LagomDevModeServiceLocatorComponents trait:

new StandaloneLagomClientFactory("my-client") with AhcWSComponents with LagomDevModeServiceLocatorComponents {
  override lazy val devModeServiceLocatorUrl =
    URI.create("http://localhost:8001")
}

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.