§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")
}