Skip to content

Gradiant/grad-servicematrix-android

Repository files navigation

Android ServiceMatrix

This is the Android Ported Version of the Walt.Id ServiceMatrix, developed by Gradiant.

Changelog

  1. build.gradle.kts -> JvmTarget for kotlin must be "11".

  2. ServiceMatrix -> Constructor and its called functions changed argument from a file path to a input stream due to the android environment nature. The config file service-matrix.properties will be located in the resource folder of the Android Project.

  3. AndroidUtils.kt -> File created to handle ServiceMatrix initialization. The variable androidDataDir is needed to create the directory structure of the wallet inside the absolute path of the Android Application. The variable dataRoot is needed to know the absolute path of the data folder inside the Android Application Directory. This variable replace the dataRoot parameter of fsStore.conf file (Previously mentioned error "No parser for .conf files"). A configuration file that it's needed to be read in runtime doesn't fit well Android, because we would need to write that file in the Android Application Directory to be able to read it later.

ServiceMatrix, by walt.id

Interchange service-implementation & service-configuration at runtime (using dynamic dependency injection), for Kotlin.

All the services, the implementations, the configurations, etc. are typesafe, as all things should be.

As of commit ff82ae5: 100% test coverage according to the JaCoCo coverage report.

Maintainer: @KBurgmann

Quickstart

Setup

Add the dependency using Gradle:

implementation("id.walt.servicematrix:waltid-servicematrix:1.1.0")

or Maven:

<dependency>
    <groupId>id.walt.servicematrix</groupId>
    <artifactId>waltid-servicematrix</artifactId>
    <version>1.1.0</version>
</dependency>

Create your first service

abstract class SimpleTestService : BaseService() {
    override val implementation get() = serviceImplementation<SimpleTestService>()

    open fun function1(): Int = implementation.function1()
    open fun function2(): String = implementation.function2()

    companion object : ServiceProvider {
        override fun getService() = object : SimpleTestService() {}
    }
}

Create your first service implementation

class SimpleTestServiceImpl1 : SimpleTestService() {
    override fun function1() = 1
    override fun function2() = "Impl 1"
}

Implementations can be inherited from implementations too!

class InheritedFromImpl1 : SimpleTestServiceImpl1() {
    override fun function2() = "The better ${super.function2()}"
}

Inject them at runtime!

Using code:

ServiceRegistry.registerService<SimpleTestService>(SimpleTestServiceImpl1())

Or using a service-matrix file:

# service-matrix.properties
ServiceMatrixTestService=ServiceMatrixTestServiceImpl1
// Load "service-matrix.properties"
ServiceMatrix("service-matrix.properties")

Define a default implementation in code

Without needing any config file! (extremely useful when using your software as a dependency)

abstract class SimpleTestService : BaseService() {
override val implementation get() = serviceImplementation<SimpleTestService>()

    open fun function1(): Int = implementation.function1()
    open fun function2(): String = implementation.function2()

    companion object : ServiceProvider {
        override fun getService() = object : SimpleTestService() {}
        override fun defaultImplementation() = SimpleTestServiceImpl1()
    }
}

Want your implementation to have configuration too?

Your new service implementation:

class ConfigurationTestServiceImpl1(configurationPath: String) : ConfigurationTestService() {
    data class SomeExtraThings(val name: String)
    data class MyConfig1(val env: String, val someExtraThings: SomeExtraThings) : ServiceConfiguration

    override val configuration: MyConfig1 = fromConfiguration(configurationPath)

    override fun someInfoText(): String = configuration.someExtraThings.name
}

And the matching config file:

env: "staging"
        
someExtraThings: {
    name: "Implementation Nr. 1"
}

And then register them with code:

ServiceRegistry.registerService<SimpleTestService>(SimpleTestServiceImpl1("myConfig.conf"))

Or using a service-matrix file:

# service-matrix.properties
ServiceMatrixTestService=ServiceMatrixTestServiceImpl1:myConfig.conf
// Load "service-matrix.properties"
ServiceMatrix("service-matrix.properties")

At-runtime reconfiguration

For the following service:

abstract class ReregistrationTestService : BaseService() {
    override val implementation get() = serviceImplementation<ReregistrationTestService>()

    open fun function1(): Int = implementation.function1()

    companion object : ServiceProvider {
        override fun getService() = object : ReregistrationTestService() {}
    }
}

class ReregistrationTestServiceImpl1 : ReregistrationTestService() {
    override fun function1() = 1
}

class ReregistrationTestServiceImpl2 : ReregistrationTestService() {
    override fun function1() = 2
}

The output will be:

// Register implementation 1
ServiceRegistry.registerService<ReregistrationTestService>(ReregistrationTestServiceImpl1())

val service = ReregistrationTestService.getService()

println(service.function1()) // 1

// Reregister with implementation 2
ServiceRegistry.registerService<ReregistrationTestService>(ReregistrationTestServiceImpl2())

// Still calling the same variable!
println(service.function1()) // 2

License

The Service Matrix project by walt.id is Open Source software released under the Apache 2.0 license.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages