Skip to main content

Quickstart

Please see the library functionality overview, component architecture additional examples and API documentation for more information.

The following sections describe multiple ways to start with Automorph depending on the scenario.

Script

Download and run a quickstart example using Scala CLI:

scala-cli "https://automorph.org/examples/src/main/scala/examples/Quickstart.scala"

Existing project

Build

Add the following dependency to project build configuration:

SBT

libraryDependencies ++= Seq(
"org.automorph" %% "automorph-default" % "0.2.5",
"ch.qos.logback" % "logback-classic" % "1.5.12",
)

Gradle

dependencies {
implementation group: 'org.automorph', name: 'automorph-default_3', version: '0.2.5'
implementation group: 'ch.qos.logback', name: 'logback-classic', version: '1.5.12'
}

Server

Expose an API instance for remote calls using JSON-RPC over HTTP(S).

import automorph.Default
import io.circe.generic.auto.*
import java.net.URI
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.Duration
import scala.concurrent.{Await, Future}

// Define a remote API
trait Api {
def test(some: String, n: Int): Future[String]
}

// Create server implementation of the remote API
class ApiImpl {
def test(n: Int): Future[String] =
Future(s"Hello world $n")
}
val api = new ApiImpl

// Configure JSON-RPC HTTP & WebSocket server to listen on port 9000 for requests to '/api'
val server = Default.rpcServer(9000, "/api")

// Expose the server API implementation to be called remotely
val apiServer = server.bind(api)

Await.ready(for {
// Start the JSON-RPC server
activeServer <- apiServer.init()

// Stop the JSON-RPC server
_ <- activeServer.close()
} yield (), Duration.Inf)

Client

Call a remote API using JSON-RPC over HTTP(S) via a type-safe local proxy created from an API trait.

import automorph.Default
import io.circe.generic.auto.*
import java.net.URI
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.Duration
import scala.concurrent.{Await, Future}

// Define a remote API
trait Api {
def test(n: Int): Future[String] =
}

// Configure JSON-RPC HTTP client to send POST requests to 'http://localhost:9000/api'
val client = Default.rpcClient(new URI("http://localhost:9000/api"))

// Create a type-safe local proxy for the remote API from the API trait
val remoteApi = client.bind[Api]

Await.ready(for {
// Initialize the JSON-RPC client
activeClient <- client.init()

// Call the remote API function via the local proxy
result <- remoteApi.test(1)
_ = println(result)

// Close the JSON-RPC client
_ <- activeClient.close()
} yield (), Duration.Inf)

Dynamic client

Call a remote API using JSON-RPC over HTTP(S) dynamically without using an API trait.

import automorph.Default
import io.circe.generic.auto.*
import java.net.URI
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.duration.Duration
import scala.concurrent.{Await, Future}

// Configure JSON-RPC HTTP client to send POST requests to 'http://localhost:9000/api'
val client = Default.rpcClient(new URI("http://localhost:9000/api"))

Await.ready(for {
// Initialize the JSON-RPC client
activeClient <- client.init()

// Call the remote API function dynamically without using an API trait
result <- activeClient.call[String]("test")("n" -> 1)
_ = println(result)

// Close the JSON-RPC client
_ <- activeClient.close()
} yield (), Duration.Inf)

New project

Create an SBT project containing a quickstart example from a Giter8 template:

sbt new automorph-org/automorph.g8 --name=automorph-example
cd automorph-example
sbt run

Customize the example by editing src/main/scala/examples/Quickstart.scala and build.sbt.

Application logs are saved to target/main.log using the LOG_LEVEL environment variable to set a log level (ERROR, WARN, INFO, DEBUG, TRACE).

Example project

Clone the example project and run any of the examples:

git clone --depth 1 https://github.com/automorph-org/automorph
cd automorph/examples/project
sbt run

Customize the examples by:

  • Integrating with preferred platforms by including additional plugins
  • Configuring RPC client, server or endpoint properties
  • Removing unused examples and build dependencies