REST services
Rest server module
To start, we'll create a simple REST server module in our movies project. Normally this would not go in your Android project, but for convenience we'll add it here.
Use File > New Module > Java or Kotlin Library to create a module called restserver
. Use
RunServer
as the class name.
We'll use the Apache Jersey server for our simple REST server, so we'll add its libraries to the
version catalog. To make things a bit more convenient, we'll use the version catalog [bundles]
support, allowing us to define a single name to represent a set of libraries we're using together.
show in full file gradle/libs.versions.toml
[versions]
// ...
glance="1.1.1"
jetbrainsKotlinJvm = "2.0.21"
jersey="3.1.9"
activation="2.1.3"
[libraries]
jersey-grizzly2 = { group = "org.glassfish.jersey.containers", name = "jersey-container-grizzly2-http", version.ref = "jersey" }
jersey-jetty = { group = "org.glassfish.jersey.containers", name = "jersey-container-jetty-http", version.ref = "jersey" }
jersey-servlet = { group = "org.glassfish.jersey.containers", name = "jersey-container-servlet-core", version.ref = "jersey" }
jersey-jackson = { group = "org.glassfish.jersey.media", name = "jersey-media-json-jackson", version.ref = "jersey" }
jersey-server = { group = "org.glassfish.jersey.core", name = "jersey-server", version.ref = "jersey" }
jersey-hk2 = { group = "org.glassfish.jersey.inject", name = "jersey-hk2", version.ref = "jersey" }
activation = { group = "jakarta.activation", name = "jakarta.activation-api", version.ref = "activation" }
glance-appwidget = { group = "androidx.glance", name = "glance-appwidget", version.ref = "glance" }
glance-material3 = { group = "androidx.glance", name = "glance-material3", version.ref = "glance" }
// ...
room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" }
[bundles]
server = [
"jersey-grizzly2",
"jersey-jetty",
"jersey-servlet",
"jersey-jackson",
"jersey-server",
"jersey-hk2",
"activation"
]
[plugins]
// ...
We add these to the new module's build.gradle.kts
using the version catalog bundle.
To run the server, we need to add the application
plugin. We don't need to add this plugin
to the version catalog as it's a standard part of the Gradle distribution. We specify the application
to run using mainClass
show in full file restserver/build.gradle.kts
plugins {
id("java-library")
alias(libs.plugins.jetbrains.kotlin.jvm)
application
}
// ...
}
dependencies {
implementation(libs.bundles.server)
}
kotlin {
// ...
}
application {
mainClass = "com.androidbyexample.compose.movies.restserver.RunServer"
}
To test that everything is set up ok to run, we'll add a simple main
to our RunServer
class
show in full file restserver/src/main/java/com/androidbyexample/compose/movies/restserver/RunServer.kt
// ...
class RunServer {
companion object {
@JvmStatic
fun main(args: Array<String>) {
println("It runs!")
}
}
}
and then we can run it via
./gradlew run
Note
Because we're running this on a Java Virtual Machine (JVM), the main class is expected to have
a public static void main(String[] args)
method. TO accomplish this, we:
- Add a
companion object
toRunServer
. Any function defined inside it belongs to theRunServer
class, and you won't need an instance ofRunServer
to execute it. - Add a
fun main(args: Array<String>)
function inside thecompanion object
- Mark the
main
function with the@JvmStatic
annotation to define the function as a static method when run on the JVM.
All code changes
CHANGED: build.gradle.kts
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.kotlin.android) apply false
alias(libs.plugins.kotlin.compose) apply false
alias(libs.plugins.android.library) apply false
alias(libs.plugins.ksp) apply false
alias(libs.plugins.jetbrains.kotlin.jvm) apply false
}
CHANGED: gradle/libs.versions.toml
[versions]
agp = "8.7.3"
kotlin = "2.0.21"
coreKtx = "1.15.0"
junit = "4.13.2"
junitVersion = "1.2.1"
espressoCore = "3.6.1"
lifecycleRuntimeKtx = "2.8.7"
activityCompose = "1.9.3"
composeBom = "2024.12.01"
appcompat = "1.7.0"
material = "1.12.0"
room = "2.6.1"
ksp = "2.0.21-1.0.28"
compileSdk = "35"
targetSdk = "35"
minSdk = "24"
jvmTarget = "11"
javaVersion = "VERSION_11"
lifecycle-compose = "2.8.7"
icons-extended = "1.7.6"
glance="1.1.1"
jetbrainsKotlinJvm = "2.0.21"
jersey="3.1.9"
activation="2.1.3"
[libraries]
jersey-grizzly2 = { group = "org.glassfish.jersey.containers", name = "jersey-container-grizzly2-http", version.ref = "jersey" }
jersey-jetty = { group = "org.glassfish.jersey.containers", name = "jersey-container-jetty-http", version.ref = "jersey" }
jersey-servlet = { group = "org.glassfish.jersey.containers", name = "jersey-container-servlet-core", version.ref = "jersey" }
jersey-jackson = { group = "org.glassfish.jersey.media", name = "jersey-media-json-jackson", version.ref = "jersey" }
jersey-server = { group = "org.glassfish.jersey.core", name = "jersey-server", version.ref = "jersey" }
jersey-hk2 = { group = "org.glassfish.jersey.inject", name = "jersey-hk2", version.ref = "jersey" }
activation = { group = "jakarta.activation", name = "jakarta.activation-api", version.ref = "activation" }
glance-appwidget = { group = "androidx.glance", name = "glance-appwidget", version.ref = "glance" }
glance-material3 = { group = "androidx.glance", name = "glance-material3", version.ref = "glance" }
icons-extended = { group = "androidx.compose.material", name = "material-icons-extended-android", version.ref = "icons-extended"}
lifecycle-compose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "lifecycle-compose" }
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
junit = { group = "junit", name = "junit", version.ref = "junit" }
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" }
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
androidx-ui = { group = "androidx.compose.ui", name = "ui" }
androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
androidx-appcompat = { group = "androidx.appcompat", name = "appcompat", version.ref = "appcompat" }
material = { group = "com.google.android.material", name = "material", version.ref = "material" }
room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" }
room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "room" }
room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" }
[bundles]
server = [
"jersey-grizzly2",
"jersey-jetty",
"jersey-servlet",
"jersey-jackson",
"jersey-server",
"jersey-hk2",
"activation"
]
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
android-library = { id = "com.android.library", version.ref = "agp" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
jetbrains-kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "jetbrainsKotlinJvm" }
ADDED: restserver/.gitignore
/build
ADDED: restserver/build.gradle.kts
plugins {
id("java-library")
alias(libs.plugins.jetbrains.kotlin.jvm)
application
}
java {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
dependencies {
implementation(libs.bundles.server)
}
kotlin {
compilerOptions {
jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_11
}
}
application {
mainClass = "com.androidbyexample.compose.movies.restserver.RunServer"
}
ADDED: restserver/src/main/java/com/androidbyexample/compose/movies/restserver/RunServer.kt
package com.androidbyexample.compose.movies.restserver
class RunServer {
companion object {
@JvmStatic
fun main(args: Array<String>) {
println("It runs!")
}
}
}
CHANGED: settings.gradle.kts
pluginManagement {
repositories {
google {
content {
includeGroupByRegex("com\\.android.*")
includeGroupByRegex("com\\.google.*")
includeGroupByRegex("androidx.*")
}
}
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
rootProject.name = "Movies"
include(":app")
include(":data")
include(":repository")
include(":restserver")