Java/Scala Protobuf SDK
Select your preferred language (Java/Scala) above.
The Kalix Java Scala SDK guides you through implementing components matching the protobuf APIs you design. This page describes prerequisites for Java Scala development and basic requirements for a development project.
Lightbend provides Tier 1 support for the Java Scala Protobuf SDK. See an explanation of support tiers for more information. |
Your development project needs to include the Kalix Java Scala Protobuf SDK and logic to start the gRPC server. You define your components in gRPC descriptors and use protoc
to compile them. Finally, you implement business logic for service components.
To save the work of starting from scratch, the Java code generation tool creates a project from a template, complete with descriptors and implementations.
Prerequisites
The following are required to develop services in Java:
- Java
-
Kalix requires Java 11 or later.
- Apache Maven
-
For Java-based services, Kalix relies on Apache Maven as build tool. The Kalix Maven plugin creates initial Java code for your components and the required surrounding code.
- sbt
-
For Scala-based services, Kalix relies on sbt as build tool. The Kalix sbt plugin creates initial Scala code for your components and the required surrounding code.
- Docker
-
Kalix requires Docker 20.10.14 for building your service images. Most popular build tools have plugins that assist in building Docker images.
Reference the Kalix Protobuf SDKs
The following examples show how to install the SDK to build your services with Maven. The code generation tools include a Kalix project template that generates the recommended project structure, including a .pom
file build.sbt with the necessary references.
In your .pom
file build.sbt, add the following:
- Java
-
<dependencies> <dependency> <groupId>io.kalix</groupId> <artifactId>kalix-java-sdk-protobuf</artifactId> <version>1.5.5</version> </dependency> <dependency> <groupId>io.kalix</groupId> <artifactId>kalix-java-sdk-protobuf-testkit</artifactId> <version>1.5.5</version> <scope>test</scope> </dependency> </dependencies>
- Scala
-
scalaVersion := "2.13.14" enablePlugins(KalixPlugin)
And in project/plugins.sbt
:
addSbtPlugin("io.kalix" % "sbt-kalix" % "1.5.5")
Configure JSON formatted logging
Kalix supports JSON formatted logging to provide multi-line messages formatted in JSON syntax. Always use JSON formatted logging for your Kalix projects to efficiently analyze and easily leverage logging information.
Build and deploy the sample to see JSON formatted logging in action. |
JSON formatted logging is enabled by default in the projects created by the Kalix project template. It includes a transitive dependency on logback-json-classic
and a logback.xml
file as shown here:
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%date{ISO8601} %-5level %logger - %msg%n</pattern>
</encoder>
</appender>
<appender name="JSON-STDOUT" target="System.out" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="kalix.javasdk.logging.LogbackJsonLayout">
<timestampFormat>yyyy-MM-dd'T'HH:mm:ss.SSSX</timestampFormat>
<timestampFormatTimezoneId>Etc/UTC</timestampFormatTimezoneId>
<appendLineSeparator>true</appendLineSeparator>
<jsonFormatter class="ch.qos.logback.contrib.jackson.JacksonJsonFormatter">
<prettyPrint>false</prettyPrint>
</jsonFormatter>
</layout>
</encoder>
</appender>
<appender name="ASYNC-JSON-STDOUT" class="ch.qos.logback.classic.AsyncAppender">
<queueSize>8192</queueSize>
<neverBlock>true</neverBlock>
<appender-ref ref="JSON-STDOUT"/>
</appender>
<logger name="akka" level="INFO"/>
<logger name="kalix" level="INFO"/>
<logger name="akka.http" level="INFO"/>
<logger name="io.grpc" level="INFO"/>
<root level="INFO">
<!-- <appender-ref ref="STDOUT"/>-->
<appender-ref ref="ASYNC-JSON-STDOUT"/>
</root>
</configuration>
In the logback.xml
you may want to adjust the log level for different loggers (typically a package or class name).
For local development you can switch to the STDOUT
appender to make the logs more readable, or use <prettyPrint>true</prettyPrint>
in the jsonFormatter
. Don’t use prettyPrint
in production since the logging infrastructure will not handle multi-line log messages.
There is a separate src/test/resources/logback-test.xml that is used when running tests.
|
Create a main class
The Kalix plugin will create a main class for you and make sure all components get registered with the Kalix server. The following code snippet shows an example that registers an Event Sourced Entity and starts the server:
- Java
-
package com.example.shoppingcart; import kalix.javasdk.Kalix; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.example.shoppingcart.domain.*; import com.example.shoppingcart.view.*; public final class Main { private static final Logger LOG = LoggerFactory.getLogger(Main.class); public static Kalix createKalix() { Kalix kalix = new Kalix(); kalix.register(ShoppingCartProvider.of(ShoppingCart::new)); kalix.register(ShoppingCartViewServiceViewProvider.of(ShoppingCartViewServiceImpl::new)); return kalix; } public static void main(String[] args) throws Exception { LOG.info("starting the Kalix service"); createKalix().start(); } }
- Scala
-
package customer import customer.action.CustomerActionImpl import customer.domain.CustomerValueEntity import customer.view.CustomerByEmailView import customer.view.CustomerByNameView import customer.view.CustomerDetailsByNameView import customer.view.CustomerSummaryByNameView import customer.view.CustomersResponseByCityView import customer.view.CustomersResponseByNameView import kalix.scalasdk.Kalix import org.slf4j.LoggerFactory // This class was initially generated based on the .proto definition by Kalix tooling. // // As long as this file exists it will not be overwritten: you can maintain it yourself, // or delete it so it is regenerated as needed. object Main { private val log = LoggerFactory.getLogger("customer.Main") def createKalix(): Kalix = { // The KalixFactory automatically registers any generated Actions, Views or Entities, // and is kept up-to-date with any changes in your protobuf definitions. // If you prefer, you may remove this and manually register these components in a // `Kalix()` instance. KalixFactory.withComponents( new CustomerValueEntity(_), new CustomerActionImpl(_), new CustomerByEmailView(_), new CustomerByNameView(_), new CustomerDetailsByNameView(_), new CustomerSummaryByNameView(_), new CustomersResponseByCityView(_), new CustomersResponseByNameView(_)) } def main(args: Array[String]): Unit = { log.info("starting the Kalix service") createKalix().start() } }