/prefiller

Prefiller is a Gradle plugin that generates pre-filled Room databases at compile time.

Primary LanguageKotlinApache License 2.0Apache-2.0

Build Status GitHub Release License

Prefiller

Prefiller is a Gradle plugin that generates pre-filled Room databases at compile time.

Motivation

With version 2.2, the Room persistence library added support for pre-populated databases. This works by including a pre-filled database in the Android app assets. Generating this database can be tedious and error-prone and has to be repeated whenever the underlying schema or data changes.

Prefiller offers a convenient way to generate pre-filled databases at compile time. You simply provide a script file which populates your database, Prefiller takes care of the rest. It will generate a database matching the latest schema, execute your script on this database and include the database in the assets. This way, changing the schema or adding additional pre-filled data is much easier. Additionally, the changes to the pre-filled database are now present in script form, making changes easier to review in pull requests.

Usage

To start using Prefiller, you just have to follow these steps.

Add Prefiller to your project

First you need to add the Prefiller plugin to your project by adding this block of code to your build.gradle.

plugins {
    id "io.github.simonschiller.prefiller" version "1.4.0"
}

Alternatively, you can also use the legacy plugin API. Simply add the following snippet to your top-level build.gradle.

buildscript {
    repositories {
        maven {
            url "https://plugins.gradle.org/m2/"
        }
    }
    dependencies {
        classpath "io.github.simonschiller:prefiller:1.4.0"
    }
}

When you're using the legacy plugin API, you also have to apply the plugin in the build.gradle of your module.

apply plugin: "io.github.simonschiller.prefiller"

You can also find instructions on how to use the Prefiller plugin on the Gradle plugin portal.

Write your setup script

Next you need to create a .sql script with all your setup statements. Simply place this file somewhere in your project. Prefiller will use this file to populate the database, so make sure the statements are valid and match the database schema. You can also supply multiple .sql files if you wish.

-- src/main/sql/setup.sql

INSERT INTO people(firstname, lastname, age) VALUES ("Mikael", "Burke", 38);
INSERT INTO people(firstname, lastname, age) VALUES ("Ayana", "Clarke", 12);
INSERT INTO people(firstname, lastname, age) VALUES ("Malachy", "Wall", 24);

Configure the Prefiller plugin

Lastly, you have to configure the Prefiller plugin in your build.gradle by linking the database class with the script file you just created.

prefiller {
    database("people") {
        classname.set("com.example.PeopleDatabase")
        scripts.from(file("src/main/sql/setup.sql"))
    }
}

Using the pre-filled database in code

Now you're ready to go. Simply use the generated database file when you build your Room database.

val database = Room.databaseBuilder(context, com.example.PeopleDatabase::class.java, "people.db")
    .createFromAsset("people.db") // File name is configured in the plugin
    .build()

How it works

Room can be set up to generate a schema definition file, this file contains all information needed to construct a matching database. Prefiller simply parses this file, generates the database accordingly and runs the provided script file. To make this work, you have to make sure that Room is configured to generate schema files.

android {
    defaultConfig {
        // Java
        javaCompileOptions {
            annotationProcessorOptions {
                arguments["room.schemaLocation"] = "$projectDir/schemas".toString()
            }
        }

        // Kotlin KAPT
        kapt {
            arguments {
                arg("room.schemaLocation", "$projectDir/schemas")
            }
        }

        // Kotlin KSP
        ksp {
            arg("room.schemaLocation", "$projectDir/schemas")
        }
    }
}

You can find more information on how to do this in the official Room documentation.

Working with this project

The source code of the plugin is located in the prefiller folder. The sample folder contains several sample projects that show how the plugin is used. The tests of these sample projects also function as E2E tests for the Prefiller plugin.

  • Build the plugin: ./gradlew :prefiller:assemble
  • Run unit tests: ./gradlew :prefiller:test
    • By default, all tests will be executed against all compatible Gradle and Android Gradle plugin versions. If you want to run tests against a specific version, you can set the GRADLE_VERSION and AGP_VERSION environment variables.
    • For example: GRADLE_VERSION=7.5.1 AGP_VERSION=7.2.2 ./gradlew :prefiller:test
  • Run all tests:
    • First publish the plugin to your local Maven repo: ./gradlew :prefiller:publishToMavenLocal
    • Then execute the tests: ./gradlew test

License

Copyright 2020 Simon Schiller

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.