Skip to content

Commit

Permalink
Merge pull request #1978 from chrisjenx/add-ktor3
Browse files Browse the repository at this point in the history
Add Ktor3 Package
  • Loading branch information
arnaudgiuliani authored Nov 15, 2024
2 parents 95ad86e + 94078cc commit 6c2aeec
Show file tree
Hide file tree
Showing 16 changed files with 863 additions and 20 deletions.
4 changes: 4 additions & 0 deletions projects/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ mockito = "4.7.0"
mockk = "1.13.2"
# Ktor
ktor = "2.3.12"
ktor3 = "3.0.0-rc-1"
slf4j = "2.0.13"
uuidVersion = "0.8.4"

Expand Down Expand Up @@ -66,6 +67,9 @@ androidx-startup = {module ="androidx.startup:startup-runtime", version.ref = "a
ktor-core = { module = "io.ktor:ktor-server-core", version.ref = "ktor" }
ktor-netty = { module = "io.ktor:ktor-server-netty", version.ref = "ktor" }
ktor-testHost = { module = "io.ktor:ktor-server-test-host", version.ref = "ktor" }
ktor3-core = { module = "io.ktor:ktor-server-core", version.ref = "ktor3" }
ktor3-netty = { module = "io.ktor:ktor-server-netty", version.ref = "ktor3" }
ktor3-testHost = { module = "io.ktor:ktor-server-test-host", version.ref = "ktor3" }
ktor-slf4j = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" }
# jetpack Compose
androidx-composeRuntime = { module = "androidx.compose.runtime:runtime", version.ref = "composeJetpackRuntime" }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package org.koin.ktor.ext

import io.ktor.server.application.*
import io.ktor.server.testing.*
import io.ktor.server.application.Application
import io.ktor.server.application.install
import io.ktor.server.testing.TestApplication
import org.junit.After
import org.junit.Assert.*
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Test
import org.koin.core.context.stopKoin
import org.koin.dsl.module
Expand All @@ -23,7 +25,7 @@ class Bar2(val name: String = "")
class KoinFeatureTest {

@After
fun after(){
fun after() {
stopKoin()
}

Expand All @@ -32,28 +34,40 @@ class KoinFeatureTest {
val module = module {
single { Foo("bar") }
}
withApplication {
application.install(Koin) {
modules(module)
val application = TestApplication {
application {
install(Koin) {
modules(module)
}
}
val bean = KoinPlatform.getKoin().getOrNull<Foo>()
assertNotNull(bean)
}
application.start()
val bean = KoinPlatform.getKoin().getOrNull<Foo>()
assertNotNull(bean)
runCatching { application.stop() }
}

@Test
fun `can install feature - isolated context`() {
val module = module {
single { Foo("bar") }
}
withApplication {
application.install(KoinIsolated) {
modules(module)
var application: Application? = null
val testApplication = TestApplication {
application {
install(KoinIsolated) {
modules(module)
}
application = this
}
val bean1 = application.get<Foo>()
assertNotNull(bean1)
val bean2 = runCatching { KoinPlatform.getKoin().getOrNull<Foo>() }.getOrNull()
assertNull(bean2)
}
testApplication.start()
// Isolated context should be limited to the application scope only
val bean1 = application?.get<Foo>()
assertNotNull(bean1)
// Isolated Koin will not be set to the global scope
val bean2 = runCatching { KoinPlatform.getKoin().getOrNull<Foo>() }.getOrNull()
assertNull(bean2)
runCatching { testApplication.stop() }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class KoinPluginRunTest {
}

@Test
@Ignore // socket exception on GH
@Ignore("socket exception on GH")
fun `run outside context`() = runBlocking<Unit> {
var counter = 0
startKoin {
Expand Down Expand Up @@ -86,7 +86,7 @@ class KoinPluginRunTest {
}

@Test
@Ignore // socket exception on GH
@Ignore("socket exception on GH")
fun `should can reload`() = runBlocking<Unit> {
val koinModule = module {
single<String> {
Expand Down
50 changes: 50 additions & 0 deletions projects/ktor/koin-ktor3/api/koin-ktor.api
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
public final class org/koin/ktor/ext/ApplicationCallExtKt {
public static final fun getKoin (Lio/ktor/server/application/ApplicationCall;)Lorg/koin/core/Koin;
public static final fun getProperty (Lio/ktor/server/application/ApplicationCall;Ljava/lang/String;)Ljava/lang/Object;
public static final fun getProperty (Lio/ktor/server/application/ApplicationCall;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
}

public final class org/koin/ktor/ext/ApplicationExtKt {
public static final fun getKoin (Lio/ktor/server/application/Application;)Lorg/koin/core/Koin;
public static final fun getProperty (Lio/ktor/server/application/Application;Ljava/lang/String;)Ljava/lang/Object;
public static final fun getProperty (Lio/ktor/server/application/Application;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
}

public final class org/koin/ktor/ext/RouteExtKt {
public static final fun getKoin (Lio/ktor/server/routing/Route;)Lorg/koin/core/Koin;
public static final fun getProperty (Lio/ktor/server/routing/Route;Ljava/lang/String;)Ljava/lang/Object;
public static final fun getProperty (Lio/ktor/server/routing/Route;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;
}

public final class org/koin/ktor/ext/RoutingExtKt {
public static final fun getKoin (Lio/ktor/server/routing/Routing;)Lorg/koin/core/Koin;
public static final fun getProperty (Lio/ktor/server/routing/Routing;Ljava/lang/String;)Ljava/lang/Object;
}

public final class org/koin/ktor/plugin/KoinApplicationEventsKt {
public static final fun getKoinApplicationStarted ()Lio/ktor/events/EventDefinition;
public static final fun getKoinApplicationStopPreparing ()Lio/ktor/events/EventDefinition;
public static final fun getKoinApplicationStopped ()Lio/ktor/events/EventDefinition;
}

public final class org/koin/ktor/plugin/KoinIsolatedContextPluginKt {
public static final fun getKoinIsolated ()Lio/ktor/server/application/ApplicationPlugin;
}

public final class org/koin/ktor/plugin/KoinPluginKt {
public static final field KOIN_KEY Ljava/lang/String;
public static final field KOIN_SCOPE_KEY Ljava/lang/String;
public static final fun getKOIN_ATTRIBUTE_KEY ()Lio/ktor/util/AttributeKey;
public static final fun getKOIN_SCOPE_ATTRIBUTE_KEY ()Lio/ktor/util/AttributeKey;
public static final fun getKoin ()Lio/ktor/server/application/ApplicationPlugin;
public static final fun getScope (Lio/ktor/server/application/ApplicationCall;)Lorg/koin/core/scope/Scope;
public static final fun koin (Lio/ktor/server/application/Application;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object;
public static final fun setKoinApplication (Lio/ktor/server/application/Application;Lorg/koin/core/KoinApplication;)V
}

public final class org/koin/ktor/plugin/RequestScope : org/koin/core/component/KoinScopeComponent {
public fun <init> (Lorg/koin/core/Koin;)V
public fun getKoin ()Lorg/koin/core/Koin;
public fun getScope ()Lorg/koin/core/scope/Scope;
}

34 changes: 34 additions & 0 deletions projects/ktor/koin-ktor3/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
kotlin("jvm")
}

dependencies {
api(project(":core:koin-core"))
testImplementation(libs.kotlin.test)
testImplementation(libs.test.junit)

// Ktor
compileOnly(libs.ktor3.core)
testImplementation(libs.ktor3.core)
testImplementation(libs.ktor3.netty)
testImplementation(libs.ktor3.testHost)
}

tasks.withType<KotlinCompile>().all {
compilerOptions {
jvmTarget.set(JvmTarget.JVM_1_8)
}
}
java {
sourceCompatibility = JavaVersion.VERSION_1_8 // or the desired Java version
targetCompatibility = JavaVersion.VERSION_1_8 // or the desired Java version
}
val sourcesJar: TaskProvider<Jar> by tasks.registering(Jar::class) {
archiveClassifier.set("sources")
from(sourceSets.main.map { it.allSource.sourceDirectories })
}

apply(from = file("../../gradle/publish-java.gradle.kts"))
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Copyright 2017-2023 the original author or authors.
*
* 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.
*/
package org.koin.ktor.ext

import io.ktor.server.application.*
import org.koin.core.Koin
import org.koin.core.parameter.ParametersDefinition
import org.koin.core.qualifier.Qualifier

/**
* Ktor Koin extensions for ApplicationCall class
*
* @author Gopal Sharma
*/

/**
* inject lazily given dependency
* @param qualifier - bean name / optional
* @param parameters
*/
inline fun <reified T : Any> ApplicationCall.inject(
qualifier: Qualifier? = null,
noinline parameters: ParametersDefinition? = null
) =
lazy { get<T>(qualifier, parameters) }

/**
* Retrieve given dependency for KoinComponent
* @param qualifier - bean name / optional
* @param parameters
*/
inline fun <reified T : Any> ApplicationCall.get(
qualifier: Qualifier? = null,
noinline parameters: ParametersDefinition? = null
) =
getKoin().get<T>(qualifier, parameters)

/**
* Retrieve given property for KoinComponent
* @param key - key property
*/
fun <T: Any> ApplicationCall.getProperty(key: String) =
getKoin().getProperty<T>(key)

/**
* Retrieve given property for KoinComponent
* give a default value if property is missing
*
* @param key - key property
* @param defaultValue - default value if property is missing
*
*/
fun ApplicationCall.getProperty(key: String, defaultValue: String) =
getKoin().getProperty(key) ?: defaultValue

/**
* Help work on ModuleDefinition
*/
fun ApplicationCall.getKoin(): Koin = application.getKoin()
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright 2017-2023 the original author or authors.
*
* 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.
*/
package org.koin.ktor.ext

import io.ktor.server.application.*
import org.koin.core.Koin
import org.koin.core.context.GlobalContext
import org.koin.core.parameter.ParametersDefinition
import org.koin.core.qualifier.Qualifier
import org.koin.dsl.KoinAppDeclaration
import org.koin.ktor.plugin.KOIN_ATTRIBUTE_KEY
import org.koin.ktor.plugin.Koin
import org.koin.ktor.plugin.setKoinApplication

/**
* Ktor Koin extensions
*
* @author Arnaud Giuliani
* @author Laurent Baresse
*/



/**
* Help work on ModuleDefinition
*/
fun Application.getKoin(): Koin =
attributes.getOrNull(KOIN_ATTRIBUTE_KEY)?.koin ?: run {
val defaultInstance = GlobalContext.getKoinApplicationOrNull() ?: error("No Koin instance started. Use install(Koin) or startKoin()")
setKoinApplication(defaultInstance)
attributes[KOIN_ATTRIBUTE_KEY].koin
}

/**
* inject lazily given dependency
* @param qualifier - bean name / optional
* @param parameters
*/
inline fun <reified T : Any> Application.inject(
qualifier: Qualifier? = null,
noinline parameters: ParametersDefinition? = null
) =
lazy { get<T>(qualifier, parameters) }

/**
* Retrieve given dependency for KoinComponent
* @param qualifier - bean name / optional
* @param parameters
*/
inline fun <reified T : Any> Application.get(
qualifier: Qualifier? = null,
noinline parameters: ParametersDefinition? = null
) =
getKoin().get<T>(qualifier, parameters)

/**
* Retrieve given property for KoinComponent
* @param key - key property
*/
fun <T : Any> Application.getProperty(key: String) =
getKoin().getProperty<T>(key)

/**
* Retrieve given property for KoinComponent
* give a default value if property is missing
*
* @param key - key property
* @param defaultValue - default value if property is missing
*
*/
fun Application.getProperty(key: String, defaultValue: String) =
getKoin().getProperty(key) ?: defaultValue
Loading

0 comments on commit 6c2aeec

Please sign in to comment.