From 5cc957b055dc682c6ebe01e9e5ca267bd50885b4 Mon Sep 17 00:00:00 2001 From: jaguililla Date: Wed, 1 Mar 2023 18:41:22 +0100 Subject: [PATCH 1/3] Set new release version --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index cdc8effc76..523659101a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ org.gradle.warning.mode=all org.gradle.console=plain # Gradle -version=2.6.2 +version=2.6.3 group=com.hexagonkt description=The atoms of your platform From feb8f3da58b25a21ad048155af7d79031725fff7 Mon Sep 17 00:00:00 2001 From: jaguililla Date: Thu, 9 Mar 2023 11:51:23 +0100 Subject: [PATCH 2/3] Update dependencies and improve handlers --- build.gradle.kts | 9 ++- gradle.properties | 6 +- gradle/dokka.gradle | 1 + gradle/jmh.gradle | 25 ++++++ gradle/wrapper/gradle-wrapper.properties | 4 +- handlers/build.gradle.kts | 2 + .../com/hexagonkt/handlers}/JmhBenchmark.kt | 29 ++++++- .../com/hexagonkt/handlers/AfterHandler.kt | 14 ++-- .../com/hexagonkt/handlers/ChainHandler.kt | 17 ++-- .../kotlin/com/hexagonkt/handlers/Context.kt | 15 +++- .../com/hexagonkt/handlers/FilterHandler.kt | 15 +++- .../kotlin/com/hexagonkt/handlers/Handler.kt | 12 +-- .../kotlin/com/hexagonkt/handlers/Handlers.kt | 4 - .../com/hexagonkt/handlers/OnHandler.kt | 11 ++- .../com/hexagonkt/handlers/EventContext.kt | 21 +---- .../http/server/handlers/Handlers.kt | 6 +- .../http/server/handlers/HttpHandler.kt | 74 +---------------- .../http/server/handlers/HttpServerContext.kt | 79 +++++++++++++------ .../server/handlers/HttpServerPredicate.kt | 9 ++- .../http/server/handlers/PathHandler.kt | 26 +++++- .../http/server/callbacks/UrlCallbackTest.kt | 7 +- .../http/server/examples/Examples.kt | 2 +- .../server/handlers/HttpServerContextTest.kt | 49 ++++++------ .../handlers/HttpServerPredicateTest.kt | 9 +-- .../http/server/handlers/HttpServerTest.kt | 4 +- .../http/server/handlers/ServerBuilderTest.kt | 2 +- .../http/server/netty/NettyServerHandler.kt | 2 +- .../http/server/servlet/ServletFilter.kt | 1 + http_test/build.gradle.kts | 26 +----- .../http/test/examples/SamplesTest.kt | 7 +- site/build.gradle.kts | 1 + site/mkdocs/index.html | 2 +- 32 files changed, 249 insertions(+), 242 deletions(-) create mode 100644 gradle/jmh.gradle rename {http_test/src/jmh/kotlin/com/hexagonkt/http/test => handlers/src/jmh/kotlin/com/hexagonkt/handlers}/JmhBenchmark.kt (80%) delete mode 100644 handlers/src/main/kotlin/com/hexagonkt/handlers/Handlers.kt rename handlers/src/{main => test}/kotlin/com/hexagonkt/handlers/EventContext.kt (60%) diff --git a/build.gradle.kts b/build.gradle.kts index c2b0344edc..508ba8e9a8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,6 +4,7 @@ import com.github.jk1.license.render.CsvReportRenderer import com.github.jk1.license.render.InventoryHtmlReportRenderer import com.github.jk1.license.render.InventoryMarkdownReportRenderer import com.github.jk1.license.render.ReportRenderer +import io.gitlab.arturbosch.detekt.Detekt /* * Main build script, responsible for: @@ -23,11 +24,11 @@ plugins { id("idea") id("eclipse") id("project-report") - id("org.jetbrains.dokka") version("1.7.20") + id("org.jetbrains.dokka") version("1.8.10") id("com.github.jk1.dependency-license-report") version("2.1") id("org.jetbrains.kotlinx.binary-compatibility-validator") version("0.13.0") id("io.gitlab.arturbosch.detekt") version("1.22.0") apply(false) - id("me.champeau.jmh") version("0.6.8") apply(false) + id("me.champeau.jmh") version("0.7.0") apply(false) } apply(from = "gradle/certificates.gradle") @@ -95,3 +96,7 @@ gradle.taskGraph.whenReady(closureOf { apiValidation { validationDisabled = true } + +subprojects { + apply(from = "$rootDir/gradle/detekt.gradle") +} diff --git a/gradle.properties b/gradle.properties index 523659101a..4963fe285c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -34,12 +34,12 @@ iconsDirectory=content # VERSIONS kotlinVersion=1.8.10 -dokkaVersion=1.7.20 +dokkaVersion=1.8.10 mockkVersion=1.13.4 junitVersion=5.9.2 -gatlingVersion=3.9.1 +gatlingVersion=3.9.2 jmhVersion=1.36 -mkdocsMaterialVersion=9.0.15 +mkdocsMaterialVersion=9.1.1 mermaidDokkaVersion=0.4.4 nativeToolsVersion=0.9.20 diff --git a/gradle/dokka.gradle b/gradle/dokka.gradle index 053e8eb676..3289d1b403 100644 --- a/gradle/dokka.gradle +++ b/gradle/dokka.gradle @@ -28,6 +28,7 @@ setUpDokka(dokkaHtmlPartial) setUpDokka(dokkaJavadoc) private void setUpDokka(final Object dokkaTask) { + dokkaTask.dependsOn("compileJava", "compileKotlin") dokkaTask.moduleName.set(project.name) dokkaTask.offlineMode.set(true) dokkaTask.dokkaSourceSets { diff --git a/gradle/jmh.gradle b/gradle/jmh.gradle new file mode 100644 index 0000000000..de0fccf885 --- /dev/null +++ b/gradle/jmh.gradle @@ -0,0 +1,25 @@ +/* + * Check usage information at: http://hexagonkt.com/gradle/#jmh + */ + +apply(plugin: "me.champeau.jmh") + +tasks.compileJmhKotlin.kotlinOptions.jvmTarget = tasks.compileKotlin.kotlinOptions.jvmTarget +tasks.compileJmhKotlin.kotlinOptions.apiVersion = tasks.compileKotlin.kotlinOptions.apiVersion + +jmh { + final String jhmVersion = findProperty("jhmVersion") ?: "1.36" + + jmhVersion.set(jhmVersion) + benchmarkMode.set(["thrpt"]) + + iterations.set(10) + batchSize.set(1) + fork.set(1) + operationsPerInvocation.set(5) + timeOnIteration.set("1s") + + warmup.set("1s") + warmupBatchSize.set(5) + warmupIterations.set(1) +} diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 7f1112b9ba..cf778f9515 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,8 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -# TODO Use Gradle 8 when Dokka support it -#distributionUrl=https://services.gradle.org/distributions/gradle-8.0.1-all.zip -distributionUrl=https://services.gradle.org/distributions/gradle-7.6.1-all.zip +distributionUrl=https://services.gradle.org/distributions/gradle-8.0.2-all.zip networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/handlers/build.gradle.kts b/handlers/build.gradle.kts index 0d636b25de..cc646485a3 100644 --- a/handlers/build.gradle.kts +++ b/handlers/build.gradle.kts @@ -1,10 +1,12 @@ plugins { id("java-library") + id("me.champeau.jmh") } apply(from = "../gradle/kotlin.gradle") apply(from = "../gradle/publish.gradle") apply(from = "../gradle/dokka.gradle") +apply(from = "../gradle/jmh.gradle") description = "Handlers to be applied on events processing." diff --git a/http_test/src/jmh/kotlin/com/hexagonkt/http/test/JmhBenchmark.kt b/handlers/src/jmh/kotlin/com/hexagonkt/handlers/JmhBenchmark.kt similarity index 80% rename from http_test/src/jmh/kotlin/com/hexagonkt/http/test/JmhBenchmark.kt rename to handlers/src/jmh/kotlin/com/hexagonkt/handlers/JmhBenchmark.kt index 8bd98149b9..f59d5295d5 100644 --- a/http_test/src/jmh/kotlin/com/hexagonkt/http/test/JmhBenchmark.kt +++ b/handlers/src/jmh/kotlin/com/hexagonkt/handlers/JmhBenchmark.kt @@ -1,4 +1,4 @@ -package com.hexagonkt.http.test +package com.hexagonkt.handlers import com.hexagonkt.handlers.* import org.openjdk.jmh.annotations.Benchmark @@ -9,6 +9,33 @@ import org.openjdk.jmh.infra.Blackhole @State(Scope.Benchmark) open class JmhBenchmark { + data class EventContext( + override val event: T, + override val predicate: (Context) -> Boolean, + override val nextHandlers: List> = emptyList(), + override val nextHandler: Int = 0, + override val exception: Exception? = null, + override val attributes: Map<*, *> = emptyMap(), + ) : Context { + + override fun with( + event: T, + predicate: (Context) -> Boolean, + nextHandlers: List>, + nextHandler: Int, + exception: Exception?, + attributes: Map<*, *>, + ): EventContext = + copy( + event = event, + predicate = predicate, + nextHandlers = nextHandlers, + nextHandler = nextHandler, + exception = exception, + attributes = attributes, + ) + } + private fun Handler.process(event: T): T = process(EventContext(event, predicate)).event diff --git a/handlers/src/main/kotlin/com/hexagonkt/handlers/AfterHandler.kt b/handlers/src/main/kotlin/com/hexagonkt/handlers/AfterHandler.kt index cd94fe61aa..106f7058ed 100644 --- a/handlers/src/main/kotlin/com/hexagonkt/handlers/AfterHandler.kt +++ b/handlers/src/main/kotlin/com/hexagonkt/handlers/AfterHandler.kt @@ -9,16 +9,16 @@ package com.hexagonkt.handlers * Their filter is evaluated after the `next` call, not before. */ data class AfterHandler( - val afterPredicate: Predicate = { true }, - val afterCallback: Callback, + val afterPredicate: (Context) -> Boolean = { true }, + override val callback: (Context) -> Context, ) : Handler { - override val predicate: Predicate = { true } + override val predicate: (Context) -> Boolean = { true } - override val callback: Callback = { - val next = it.next().with(predicate = afterPredicate) - try { - if (afterPredicate.invoke(next)) afterCallback(next) + override fun process(context: Context): Context { + val next = context.next().with(predicate = afterPredicate) + return try { + if (afterPredicate.invoke(next)) callback(next) else next } catch (e: Exception) { diff --git a/handlers/src/main/kotlin/com/hexagonkt/handlers/ChainHandler.kt b/handlers/src/main/kotlin/com/hexagonkt/handlers/ChainHandler.kt index 9d51e8ed4c..e0e2d7cb7f 100644 --- a/handlers/src/main/kotlin/com/hexagonkt/handlers/ChainHandler.kt +++ b/handlers/src/main/kotlin/com/hexagonkt/handlers/ChainHandler.kt @@ -2,24 +2,27 @@ package com.hexagonkt.handlers data class ChainHandler( val handlers: List>, - override val predicate: Predicate = { true }, + override val predicate: (Context) -> Boolean = { true }, ) : Handler { + override val callback: (Context) -> Context = { it } + constructor( - filter: Predicate, + filter: (Context) -> Boolean, vararg handlers: Handler, ) : this(handlers.toList(), filter) constructor(vararg handlers: Handler) : this(handlers.toList(), { true }) - override val callback: Callback = { - val nestedContext = it.with(event = it.event, nextHandlers = handlers, nextHandler = 0) + override fun process(context: Context): Context { + val event = context.event + val nestedContext = context.with(event = event, nextHandlers = handlers, nextHandler = 0) val nestedResult = nestedContext.next() val followUpContext = nestedResult.with( predicate = predicate, - nextHandlers = it.nextHandlers, - nextHandler = it.nextHandler + nextHandlers = context.nextHandlers, + nextHandler = context.nextHandler ) - followUpContext.next() + return followUpContext.next() } } diff --git a/handlers/src/main/kotlin/com/hexagonkt/handlers/Context.kt b/handlers/src/main/kotlin/com/hexagonkt/handlers/Context.kt index c5d40668ad..c6ad6fe569 100644 --- a/handlers/src/main/kotlin/com/hexagonkt/handlers/Context.kt +++ b/handlers/src/main/kotlin/com/hexagonkt/handlers/Context.kt @@ -7,7 +7,7 @@ package com.hexagonkt.handlers */ interface Context { val event: T - val predicate: Predicate + val predicate: (Context) -> Boolean val nextHandlers: List> val nextHandler: Int val exception: Exception? @@ -15,12 +15,21 @@ interface Context { fun with( event: T = this.event, - predicate: Predicate = this.predicate, + predicate: (Context) -> Boolean = this.predicate, nextHandlers: List> = this.nextHandlers, nextHandler: Int = this.nextHandler, exception: Exception? = this.exception, attributes: Map<*, *> = this.attributes, ): Context - fun next(): Context + fun next(): Context { + for (index in nextHandler until nextHandlers.size) { + val handler = nextHandlers[index] + val p = handler.predicate + if (p(this)) + return handler.process(with(predicate = p, nextHandler = index + 1)) + } + + return this + } } diff --git a/handlers/src/main/kotlin/com/hexagonkt/handlers/FilterHandler.kt b/handlers/src/main/kotlin/com/hexagonkt/handlers/FilterHandler.kt index 5b2036c3da..758fa67ac4 100644 --- a/handlers/src/main/kotlin/com/hexagonkt/handlers/FilterHandler.kt +++ b/handlers/src/main/kotlin/com/hexagonkt/handlers/FilterHandler.kt @@ -1,6 +1,15 @@ package com.hexagonkt.handlers data class FilterHandler( - override val predicate: Predicate = { true }, - override val callback: Callback, -) : Handler + override val predicate: (Context) -> Boolean = { true }, + override val callback: (Context) -> Context, +) : Handler { + + override fun process(context: Context): Context = + try { + callback(context) + } + catch (e: Exception) { + context.with(exception = e) + } +} diff --git a/handlers/src/main/kotlin/com/hexagonkt/handlers/Handler.kt b/handlers/src/main/kotlin/com/hexagonkt/handlers/Handler.kt index e929ee3990..20895c06d0 100644 --- a/handlers/src/main/kotlin/com/hexagonkt/handlers/Handler.kt +++ b/handlers/src/main/kotlin/com/hexagonkt/handlers/Handler.kt @@ -6,14 +6,8 @@ package com.hexagonkt.handlers * @param T Event type. */ interface Handler { - val predicate: Predicate - val callback: Callback + val predicate: (Context) -> Boolean + val callback: (Context) -> Context - fun process(context: Context): Context = - try { - callback(context) - } - catch (e: Exception) { - context.with(exception = e) - } + fun process(context: Context): Context } diff --git a/handlers/src/main/kotlin/com/hexagonkt/handlers/Handlers.kt b/handlers/src/main/kotlin/com/hexagonkt/handlers/Handlers.kt deleted file mode 100644 index 4c4926604b..0000000000 --- a/handlers/src/main/kotlin/com/hexagonkt/handlers/Handlers.kt +++ /dev/null @@ -1,4 +0,0 @@ -package com.hexagonkt.handlers - -typealias Predicate = (Context) -> Boolean -typealias Callback = (Context) -> Context diff --git a/handlers/src/main/kotlin/com/hexagonkt/handlers/OnHandler.kt b/handlers/src/main/kotlin/com/hexagonkt/handlers/OnHandler.kt index 3163d641b6..88a2e1eb92 100644 --- a/handlers/src/main/kotlin/com/hexagonkt/handlers/OnHandler.kt +++ b/handlers/src/main/kotlin/com/hexagonkt/handlers/OnHandler.kt @@ -1,16 +1,15 @@ package com.hexagonkt.handlers data class OnHandler( - override val predicate: Predicate = { true }, - val beforeCallback: Callback, + override val predicate: (Context) -> Boolean = { true }, + override val callback: (Context) -> Context, ) : Handler { - override val callback: Callback = { + override fun process(context: Context): Context = try { - beforeCallback(it).next() + callback(context).next() } catch (e: Exception) { - it.with(exception = e).next() + context.with(exception = e).next() } - } } diff --git a/handlers/src/main/kotlin/com/hexagonkt/handlers/EventContext.kt b/handlers/src/test/kotlin/com/hexagonkt/handlers/EventContext.kt similarity index 60% rename from handlers/src/main/kotlin/com/hexagonkt/handlers/EventContext.kt rename to handlers/src/test/kotlin/com/hexagonkt/handlers/EventContext.kt index a49b8f7cae..ff4a67b89c 100644 --- a/handlers/src/main/kotlin/com/hexagonkt/handlers/EventContext.kt +++ b/handlers/src/test/kotlin/com/hexagonkt/handlers/EventContext.kt @@ -1,13 +1,8 @@ package com.hexagonkt.handlers -/** - * Context for an event. - * - * @param T Event type. - */ data class EventContext( override val event: T, - override val predicate: Predicate, + override val predicate: (Context) -> Boolean, override val nextHandlers: List> = emptyList(), override val nextHandler: Int = 0, override val exception: Exception? = null, @@ -16,7 +11,7 @@ data class EventContext( override fun with( event: T, - predicate: Predicate, + predicate: (Context) -> Boolean, nextHandlers: List>, nextHandler: Int, exception: Exception?, @@ -30,16 +25,4 @@ data class EventContext( exception = exception, attributes = attributes, ) - - override fun next(): Context { - for (index in nextHandler until nextHandlers.size) { - val handler = nextHandlers[index] - if (handler.predicate(this)) - return handler.process( - with(predicate = handler.predicate, nextHandler = index + 1) - ) - } - - return this - } } diff --git a/http_server/src/main/kotlin/com/hexagonkt/http/server/handlers/Handlers.kt b/http_server/src/main/kotlin/com/hexagonkt/http/server/handlers/Handlers.kt index 826da4a846..d925ffa54c 100644 --- a/http_server/src/main/kotlin/com/hexagonkt/http/server/handlers/Handlers.kt +++ b/http_server/src/main/kotlin/com/hexagonkt/http/server/handlers/Handlers.kt @@ -1,6 +1,6 @@ package com.hexagonkt.http.server.handlers -import com.hexagonkt.handlers.Callback +import com.hexagonkt.handlers.Context import com.hexagonkt.http.model.* import com.hexagonkt.http.model.HttpMethod.* import com.hexagonkt.http.model.HttpProtocol.HTTP @@ -13,8 +13,8 @@ import kotlin.reflect.cast typealias HttpCallback = HttpServerContext.() -> HttpServerContext typealias HttpExceptionCallback = HttpServerContext.(T) -> HttpServerContext -internal fun toCallback(handler: HttpCallback): Callback = - { context -> HttpServerContext(context).handler().context } +internal fun toCallback(block: HttpCallback): (Context) -> Context = + { context -> HttpServerContext(context).block() } fun HttpCallback.process( request: HttpServerRequest, diff --git a/http_server/src/main/kotlin/com/hexagonkt/http/server/handlers/HttpHandler.kt b/http_server/src/main/kotlin/com/hexagonkt/http/server/handlers/HttpHandler.kt index 89514662d2..e838973b9a 100644 --- a/http_server/src/main/kotlin/com/hexagonkt/http/server/handlers/HttpHandler.kt +++ b/http_server/src/main/kotlin/com/hexagonkt/http/server/handlers/HttpHandler.kt @@ -1,19 +1,9 @@ package com.hexagonkt.http.server.handlers -import com.hexagonkt.core.media.TEXT_PLAIN -import com.hexagonkt.core.toText -import com.hexagonkt.handlers.Context -import com.hexagonkt.handlers.EventContext import com.hexagonkt.handlers.Handler import com.hexagonkt.http.model.* -import com.hexagonkt.http.model.HttpMethod.GET -import com.hexagonkt.http.model.HttpProtocol.HTTP -import com.hexagonkt.http.model.HttpStatusType.SERVER_ERROR import com.hexagonkt.http.server.model.HttpServerCall -import com.hexagonkt.http.server.model.HttpServerRequest import com.hexagonkt.http.server.model.HttpServerRequestPort -import com.hexagonkt.http.server.model.HttpServerResponse -import java.security.cert.X509Certificate sealed interface HttpHandler : Handler { val serverPredicate: HttpServerPredicate @@ -46,65 +36,9 @@ sealed interface HttpHandler : Handler { copy(serverPredicate = serverPredicate.clearMethods()) } - fun processContext(request: HttpServerRequestPort): Context = - process(EventContext(HttpServerCall(request = request), predicate)).let { - val event = it.event - val response = event.response - val exception = it.exception - - if (exception != null && response.status.type != SERVER_ERROR) - it.with( - event = event.copy( - response = response.copy( - body = exception.toText(), - contentType = ContentType(TEXT_PLAIN), - status = INTERNAL_SERVER_ERROR_500, - ) - ) - ) - else it + fun process(request: HttpServerRequestPort): HttpServerContext = + HttpServerContext(HttpServerCall(request = request), predicate).let { context -> + if (serverPredicate(context)) process(context) as HttpServerContext + else context } - - fun process(request: HttpServerRequestPort): HttpServerResponse = - EventContext(HttpServerCall(request = request), predicate).let { context -> - if (serverPredicate(context)) process(context).event.response - else context.event.response - } - - fun process( - method: HttpMethod = GET, - protocol: HttpProtocol = HTTP, - host: String = "localhost", - port: Int = 80, - path: String = "", - queryParameters: QueryParameters = QueryParameters(), - headers: Headers = Headers(), - body: Any = "", - parts: List = emptyList(), - formParameters: FormParameters = FormParameters(), - cookies: List = emptyList(), - contentType: ContentType? = null, - certificateChain: List = emptyList(), - accept: List = emptyList(), - contentLength: Long = -1L, - ): HttpServerResponse = - process( - HttpServerRequest( - method, - protocol, - host, - port, - path, - queryParameters, - headers, - body, - parts, - formParameters, - cookies, - contentType, - certificateChain, - accept, - contentLength, - ) - ) } diff --git a/http_server/src/main/kotlin/com/hexagonkt/http/server/handlers/HttpServerContext.kt b/http_server/src/main/kotlin/com/hexagonkt/http/server/handlers/HttpServerContext.kt index e40d163aed..20d0691fe7 100644 --- a/http_server/src/main/kotlin/com/hexagonkt/http/server/handlers/HttpServerContext.kt +++ b/http_server/src/main/kotlin/com/hexagonkt/http/server/handlers/HttpServerContext.kt @@ -5,7 +5,7 @@ import com.hexagonkt.core.assertEnabled import com.hexagonkt.core.media.TEXT_EVENT_STREAM import com.hexagonkt.core.media.TEXT_PLAIN import com.hexagonkt.core.toText -import com.hexagonkt.handlers.EventContext +import com.hexagonkt.handlers.Handler import com.hexagonkt.http.model.* import com.hexagonkt.http.model.INTERNAL_SERVER_ERROR_500 import com.hexagonkt.http.model.ServerEvent @@ -18,10 +18,15 @@ import java.util.concurrent.Flow.Publisher // TODO Add exception parameter to 'send*' methods data class HttpServerContext( - val context: Context -): Context by context { - val request: HttpServerRequestPort = context.event.request - val response: HttpServerResponse = context.event.response + override val event: HttpServerCall, + override val predicate: (Context) -> Boolean, + override val nextHandlers: List> = emptyList(), + override val nextHandler: Int = 0, + override val exception: Exception? = null, + override val attributes: Map<*, *> = emptyMap(), +): Context { + val request: HttpServerRequestPort = event.request + val response: HttpServerResponse = event.response val method: HttpMethod by lazy { request.method } val protocol: HttpProtocol by lazy { request.protocol } @@ -45,7 +50,7 @@ data class HttpServerContext( val status: HttpStatus = response.status val pathParameters: Map by lazy { - val httpHandler = context.predicate as HttpServerPredicate + val httpHandler = predicate as HttpServerPredicate val pattern = httpHandler.pathPattern if (assertEnabled) @@ -54,22 +59,48 @@ data class HttpServerContext( pattern.extractParameters(request.path) } + constructor(context: Context) : this( + event = context.event, + predicate = context.predicate, + nextHandlers = context.nextHandlers, + nextHandler = context.nextHandler, + exception = context.exception, + attributes = context.attributes, + ) + constructor( request: HttpServerRequestPort = HttpServerRequest(), response: HttpServerResponse = HttpServerResponse(), predicate: HttpServerPredicate = HttpServerPredicate(), attributes: Map<*, *> = emptyMap(), - ) : this(EventContext(HttpServerCall(request, response), predicate, attributes = attributes)) + ) : this(HttpServerCall(request, response), predicate, attributes = attributes) override fun next(): HttpServerContext = - HttpServerContext(context.next()) + super.next() as HttpServerContext + + override fun with( + event: HttpServerCall, + predicate: (Context) -> Boolean, + nextHandlers: List>, + nextHandler: Int, + exception: Exception?, + attributes: Map<*, *> + ): Context = + copy( + event = event, + predicate = predicate, + nextHandlers = nextHandlers, + nextHandler = nextHandler, + exception = exception, + attributes = attributes, + ) fun unauthorized( body: Any = response.body, headers: Headers = response.headers, contentType: ContentType? = response.contentType, cookies: List = response.cookies, - attributes: Map<*, *> = context.attributes, + attributes: Map<*, *> = this.attributes, ): HttpServerContext = send(UNAUTHORIZED_401, body, headers, contentType, cookies, attributes) @@ -78,7 +109,7 @@ data class HttpServerContext( headers: Headers = response.headers, contentType: ContentType? = response.contentType, cookies: List = response.cookies, - attributes: Map<*, *> = context.attributes, + attributes: Map<*, *> = this.attributes, ): HttpServerContext = send(FORBIDDEN_403, body, headers, contentType, cookies, attributes) @@ -87,7 +118,7 @@ data class HttpServerContext( headers: Headers = response.headers, contentType: ContentType? = response.contentType, cookies: List = response.cookies, - attributes: Map<*, *> = context.attributes, + attributes: Map<*, *> = this.attributes, ): HttpServerContext = send(INTERNAL_SERVER_ERROR_500, body, headers, contentType, cookies, attributes) @@ -95,7 +126,7 @@ data class HttpServerContext( status: HttpStatus, exception: Exception, headers: Headers = response.headers, - attributes: Map<*, *> = context.attributes, + attributes: Map<*, *> = this.attributes, ): HttpServerContext = send( status = status, @@ -108,7 +139,7 @@ data class HttpServerContext( fun internalServerError( exception: Exception, headers: Headers = response.headers, - attributes: Map<*, *> = context.attributes, + attributes: Map<*, *> = this.attributes, ): HttpServerContext = serverError(INTERNAL_SERVER_ERROR_500, exception, headers, attributes) @@ -117,7 +148,7 @@ data class HttpServerContext( headers: Headers = response.headers, contentType: ContentType? = response.contentType, cookies: List = response.cookies, - attributes: Map<*, *> = context.attributes, + attributes: Map<*, *> = this.attributes, ): HttpServerContext = send(OK_200, body, headers, contentType, cookies, attributes) @@ -133,7 +164,7 @@ data class HttpServerContext( headers: Headers = response.headers, contentType: ContentType? = response.contentType, cookies: List = response.cookies, - attributes: Map<*, *> = context.attributes, + attributes: Map<*, *> = this.attributes, ): HttpServerContext = send(BAD_REQUEST_400, body, headers, contentType, cookies, attributes) @@ -142,7 +173,7 @@ data class HttpServerContext( headers: Headers = response.headers, contentType: ContentType? = response.contentType, cookies: List = response.cookies, - attributes: Map<*, *> = context.attributes, + attributes: Map<*, *> = this.attributes, ): HttpServerContext = send(NOT_FOUND_404, body, headers, contentType, cookies, attributes) @@ -151,7 +182,7 @@ data class HttpServerContext( headers: Headers = response.headers, contentType: ContentType? = response.contentType, cookies: List = response.cookies, - attributes: Map<*, *> = context.attributes, + attributes: Map<*, *> = this.attributes, ): HttpServerContext = send(CREATED_201, body, headers, contentType, cookies, attributes) @@ -164,7 +195,7 @@ data class HttpServerContext( onClose: WsServerSession.(status: WsCloseStatus, reason: String) -> Unit = { _, _ -> }, ): HttpServerContext = send( - context.event.response.copy( + event.response.copy( status = ACCEPTED_202, onConnect = onConnect, onBinary = onBinary, @@ -181,7 +212,7 @@ data class HttpServerContext( headers: Headers = response.headers, contentType: ContentType? = response.contentType, cookies: List = response.cookies, - attributes: Map<*, *> = context.attributes, + attributes: Map<*, *> = this.attributes, ): HttpServerContext = send( response.copy( @@ -195,12 +226,10 @@ data class HttpServerContext( ) fun send( - response: HttpServerResponse, attributes: Map<*, *> = context.attributes + response: HttpServerResponse, attributes: Map<*, *> = this.attributes ): HttpServerContext = - HttpServerContext( - context.with( - event = context.event.copy(response = response), - attributes = attributes - ) + copy( + event = event.copy(response = response), + attributes = attributes ) } diff --git a/http_server/src/main/kotlin/com/hexagonkt/http/server/handlers/HttpServerPredicate.kt b/http_server/src/main/kotlin/com/hexagonkt/http/server/handlers/HttpServerPredicate.kt index a7a094ab46..4e8b257b05 100644 --- a/http_server/src/main/kotlin/com/hexagonkt/http/server/handlers/HttpServerPredicate.kt +++ b/http_server/src/main/kotlin/com/hexagonkt/http/server/handlers/HttpServerPredicate.kt @@ -1,7 +1,6 @@ package com.hexagonkt.http.server.handlers import com.hexagonkt.handlers.Context -import com.hexagonkt.handlers.Predicate import com.hexagonkt.core.logging.Logger import com.hexagonkt.http.patterns.LiteralPathPattern import com.hexagonkt.http.model.HttpMethod @@ -16,14 +15,14 @@ data class HttpServerPredicate( val pathPattern: PathPattern = LiteralPathPattern(), val exception: KClass? = null, val status: HttpStatus? = null, -) : Predicate { +) : (Context) -> Boolean { private val logger: Logger = Logger(HttpServerPredicate::class) private fun PathPattern.isEmpty(): Boolean = pattern.isEmpty() - val predicate: Predicate = + val predicate: (Context) -> Boolean = if (methods.isEmpty()) log(::filterWithoutMethod) else log(::filterWithMethod) @@ -42,7 +41,9 @@ data class HttpServerPredicate( fun clearMethods(): HttpServerPredicate = copy(methods = emptySet()) - private fun log(predicate: Predicate): Predicate { + private fun log( + predicate: (Context) -> Boolean + ): (Context) -> Boolean { return if (logger.isDebugEnabled()) { { val allowed = predicate(it) diff --git a/http_server/src/main/kotlin/com/hexagonkt/http/server/handlers/PathHandler.kt b/http_server/src/main/kotlin/com/hexagonkt/http/server/handlers/PathHandler.kt index 522d5637dc..d69d8cd6f3 100644 --- a/http_server/src/main/kotlin/com/hexagonkt/http/server/handlers/PathHandler.kt +++ b/http_server/src/main/kotlin/com/hexagonkt/http/server/handlers/PathHandler.kt @@ -1,12 +1,16 @@ package com.hexagonkt.http.server.handlers +import com.hexagonkt.core.media.TEXT_PLAIN +import com.hexagonkt.core.toText import com.hexagonkt.handlers.ChainHandler import com.hexagonkt.handlers.Handler +import com.hexagonkt.http.model.ContentType import com.hexagonkt.http.model.HttpMethod import com.hexagonkt.http.model.HttpMethod.Companion.ALL +import com.hexagonkt.http.model.HttpStatusType.SERVER_ERROR +import com.hexagonkt.http.model.INTERNAL_SERVER_ERROR_500 import com.hexagonkt.http.server.model.HttpServerCall import com.hexagonkt.http.server.model.HttpServerRequestPort -import com.hexagonkt.http.server.model.HttpServerResponse data class PathHandler( override val serverPredicate: HttpServerPredicate, @@ -45,8 +49,24 @@ data class PathHandler( constructor(pattern: String, vararg handlers: HttpHandler) : this(pattern, handlers.toList()) - override fun process(request: HttpServerRequestPort): HttpServerResponse = - processContext(request).event.response + override fun process(request: HttpServerRequestPort): HttpServerContext = + process(HttpServerContext(HttpServerCall(request = request), predicate)).let { + val event = it.event + val response = event.response + val exception = it.exception + + if (exception != null && response.status.type != SERVER_ERROR) + it.with( + event = event.copy( + response = response.copy( + body = exception.toText(), + contentType = ContentType(TEXT_PLAIN), + status = INTERNAL_SERVER_ERROR_500, + ) + ) + ) + else it + } as HttpServerContext override fun addPrefix(prefix: String): HttpHandler = copy(serverPredicate = serverPredicate.addPrefix(prefix)) diff --git a/http_server/src/test/kotlin/com/hexagonkt/http/server/callbacks/UrlCallbackTest.kt b/http_server/src/test/kotlin/com/hexagonkt/http/server/callbacks/UrlCallbackTest.kt index 4eecd36bf6..e48ff3eda0 100644 --- a/http_server/src/test/kotlin/com/hexagonkt/http/server/callbacks/UrlCallbackTest.kt +++ b/http_server/src/test/kotlin/com/hexagonkt/http/server/callbacks/UrlCallbackTest.kt @@ -1,6 +1,5 @@ package com.hexagonkt.http.server.callbacks -import com.hexagonkt.handlers.EventContext import com.hexagonkt.core.media.TEXT_PLAIN import com.hexagonkt.http.model.ContentType import com.hexagonkt.http.model.NOT_FOUND_404 @@ -78,10 +77,8 @@ internal class UrlCallbackTest { ): HttpServerResponse = UrlCallback(URL(url))( HttpServerContext( - EventContext( - HttpServerCall(HttpServerRequest(path = requestPath)), - HttpServerPredicate(pathPattern = TemplatePathPattern(pathPattern)) - ) + HttpServerCall(HttpServerRequest(path = requestPath)), + HttpServerPredicate(pathPattern = TemplatePathPattern(pathPattern)) ) ).response } diff --git a/http_server/src/test/kotlin/com/hexagonkt/http/server/examples/Examples.kt b/http_server/src/test/kotlin/com/hexagonkt/http/server/examples/Examples.kt index a1e5b9af2d..9f48b750e1 100644 --- a/http_server/src/test/kotlin/com/hexagonkt/http/server/examples/Examples.kt +++ b/http_server/src/test/kotlin/com/hexagonkt/http/server/examples/Examples.kt @@ -37,7 +37,7 @@ internal fun HttpHandler.send( queryParameters = parseQueryString(query) ) .auth(user, password) - ) + ).response internal fun HttpServerRequest.auth( user: String? = null, password: String? = null): HttpServerRequest { diff --git a/http_server/src/test/kotlin/com/hexagonkt/http/server/handlers/HttpServerContextTest.kt b/http_server/src/test/kotlin/com/hexagonkt/http/server/handlers/HttpServerContextTest.kt index 4ac56c2635..8d4bfa00b7 100644 --- a/http_server/src/test/kotlin/com/hexagonkt/http/server/handlers/HttpServerContextTest.kt +++ b/http_server/src/test/kotlin/com/hexagonkt/http/server/handlers/HttpServerContextTest.kt @@ -1,6 +1,5 @@ package com.hexagonkt.http.server.handlers -import com.hexagonkt.handlers.EventContext import com.hexagonkt.core.media.TEXT_HTML import com.hexagonkt.core.media.TEXT_PLAIN import com.hexagonkt.http.model.* @@ -45,23 +44,23 @@ internal class HttpServerContextTest { predicate = HttpServerPredicate(pathPattern = TemplatePathPattern("/path/{p1}")), ) - assertSame(context.method, context.context.event.request.method) - assertSame(context.protocol, context.context.event.request.protocol) - assertSame(context.host, context.context.event.request.host) - assertEquals(context.port, context.context.event.request.port) - assertSame(context.path, context.context.event.request.path) - assertSame(context.queryParameters, context.context.event.request.queryParameters) - assertSame(context.parts, context.context.event.request.parts) - assertSame(context.formParameters, context.context.event.request.formParameters) - assertSame(context.accept, context.context.event.request.accept) - assertSame(context.certificateChain, context.context.event.request.certificateChain) - assertEquals(context.partsMap, context.context.event.request.partsMap()) - assertEquals(context.url, context.context.event.request.url()) - assertSame(context.userAgent, context.context.event.request.userAgent()) - assertSame(context.referer, context.context.event.request.referer()) - assertSame(context.origin, context.context.event.request.origin()) - assertSame(context.certificate, context.context.event.request.certificate()) - assertSame(context.status, context.context.event.response.status) + assertSame(context.method, context.event.request.method) + assertSame(context.protocol, context.event.request.protocol) + assertSame(context.host, context.event.request.host) + assertEquals(context.port, context.event.request.port) + assertSame(context.path, context.event.request.path) + assertSame(context.queryParameters, context.event.request.queryParameters) + assertSame(context.parts, context.event.request.parts) + assertSame(context.formParameters, context.event.request.formParameters) + assertSame(context.accept, context.event.request.accept) + assertSame(context.certificateChain, context.event.request.certificateChain) + assertEquals(context.partsMap, context.event.request.partsMap()) + assertEquals(context.url, context.event.request.url()) + assertSame(context.userAgent, context.event.request.userAgent()) + assertSame(context.referer, context.event.request.referer()) + assertSame(context.origin, context.event.request.origin()) + assertSame(context.certificate, context.event.request.certificate()) + assertSame(context.status, context.event.response.status) } @Test fun `Send without parameters return the same response`() { @@ -105,13 +104,13 @@ internal class HttpServerContextTest { path.process(HttpServerRequest(path = "/internalServerError")).status ) - path.process(HttpServerRequest(path = "/internalServerErrorException")).let { + path.process(HttpServerRequest(path = "/internalServerErrorException")).response.let { assertEquals(INTERNAL_SERVER_ERROR_500, it.status) assertTrue(it.bodyString().contains(RuntimeException::class.java.name)) assertEquals(ContentType(TEXT_PLAIN), it.contentType) } - path.process(HttpServerRequest(path = "/serverErrorException")).let { + path.process(HttpServerRequest(path = "/serverErrorException")).response.let { assertEquals(BAD_GATEWAY_502, it.status) assertTrue(it.bodyString().contains(RuntimeException::class.java.name)) assertEquals(ContentType(TEXT_PLAIN), it.contentType) @@ -120,12 +119,10 @@ internal class HttpServerContextTest { @Test fun `'next' executes the next handler in the chain`() { val context = HttpServerContext( - EventContext( - HttpServerCall(httpServerRequest(), HttpServerResponse()), - HttpServerPredicate(), - listOf( - OnHandler("*") { ok() }, - ) + HttpServerCall(httpServerRequest(), HttpServerResponse()), + HttpServerPredicate(), + listOf( + OnHandler("*") { ok() }, ) ) diff --git a/http_server/src/test/kotlin/com/hexagonkt/http/server/handlers/HttpServerPredicateTest.kt b/http_server/src/test/kotlin/com/hexagonkt/http/server/handlers/HttpServerPredicateTest.kt index 6981bf68de..b8af3bede2 100644 --- a/http_server/src/test/kotlin/com/hexagonkt/http/server/handlers/HttpServerPredicateTest.kt +++ b/http_server/src/test/kotlin/com/hexagonkt/http/server/handlers/HttpServerPredicateTest.kt @@ -1,6 +1,5 @@ package com.hexagonkt.http.server.handlers -import com.hexagonkt.handlers.EventContext import com.hexagonkt.http.model.HttpStatus import com.hexagonkt.http.model.HttpMethod import com.hexagonkt.http.model.HttpMethod.* @@ -22,13 +21,13 @@ internal class HttpServerPredicateTest { @Test fun `Predicates with empty pattern matches exact path or root`() { val predicate = HttpServerPredicate() val call = HttpServerCall(HttpServerRequest(), HttpServerResponse()) - val context = EventContext(call, predicate) + val context = HttpServerContext(call, predicate) assertTrue(predicate(context)) val call1 = HttpServerCall(HttpServerRequest(path = "/"), HttpServerResponse()) - val context1 = EventContext(call1, predicate) + val context1 = HttpServerContext(call1, predicate) assertTrue(predicate(context1)) val call2 = HttpServerCall(HttpServerRequest(path = "/a"), HttpServerResponse()) - val context2 = EventContext(call2, predicate) + val context2 = HttpServerContext(call2, predicate) assertFalse(predicate(context2)) } @@ -197,7 +196,7 @@ internal class HttpServerPredicateTest { status: HttpStatus, exception: Exception? = null, ) = - EventContext( + HttpServerContext( HttpServerCall( HttpServerRequest(method = method, path = path), HttpServerResponse(status = status) diff --git a/http_server/src/test/kotlin/com/hexagonkt/http/server/handlers/HttpServerTest.kt b/http_server/src/test/kotlin/com/hexagonkt/http/server/handlers/HttpServerTest.kt index 86b3ea1ac8..740fd1bdb3 100644 --- a/http_server/src/test/kotlin/com/hexagonkt/http/server/handlers/HttpServerTest.kt +++ b/http_server/src/test/kotlin/com/hexagonkt/http/server/handlers/HttpServerTest.kt @@ -45,9 +45,9 @@ internal class HttpServerTest { assertEquals(NO_CONTENT_204, path.process(HttpServerRequest(path = "/a/b")).status) assertEquals(METHOD_NOT_ALLOWED_405, path.process(HttpServerRequest(PUT, path = "/a/b")).status) assertEquals(OK_200, path.process(HttpServerRequest(path = "/a/x")).status) - assertEquals("x", path.process(HttpServerRequest(path = "/a/x")).body) + assertEquals("x", path.process(HttpServerRequest(path = "/a/x")).response.body) assertEquals(OK_200, path.process(HttpServerRequest(path = "/a/b/value")).status) - assertEquals("value", path.process(HttpServerRequest(path = "/a/b/value")).body) + assertEquals("value", path.process(HttpServerRequest(path = "/a/b/value")).response.body) } @Test fun `Builder proof of concept`() { diff --git a/http_server/src/test/kotlin/com/hexagonkt/http/server/handlers/ServerBuilderTest.kt b/http_server/src/test/kotlin/com/hexagonkt/http/server/handlers/ServerBuilderTest.kt index 2ee84b807b..58cc755949 100644 --- a/http_server/src/test/kotlin/com/hexagonkt/http/server/handlers/ServerBuilderTest.kt +++ b/http_server/src/test/kotlin/com/hexagonkt/http/server/handlers/ServerBuilderTest.kt @@ -120,7 +120,7 @@ internal class ServerBuilderTest { } private fun body(path: PathHandler, value: String): String = - path.process(HttpServerRequest(path = value)).body as String + path.process(HttpServerRequest(path = value)).response.body as String @Suppress("SameParameterValue") // Not relevant in tests private fun predicate(pattern: String): HttpServerPredicate = diff --git a/http_server_netty/src/main/kotlin/com/hexagonkt/http/server/netty/NettyServerHandler.kt b/http_server_netty/src/main/kotlin/com/hexagonkt/http/server/netty/NettyServerHandler.kt index e7db95d3fe..52ccb5bb54 100644 --- a/http_server_netty/src/main/kotlin/com/hexagonkt/http/server/netty/NettyServerHandler.kt +++ b/http_server_netty/src/main/kotlin/com/hexagonkt/http/server/netty/NettyServerHandler.kt @@ -59,7 +59,7 @@ internal class NettyServerHandler( val headers = nettyRequest.headers() val request = NettyRequestAdapter(method, nettyRequest, certificates, address, headers) - val resultContext = pathHandler.processContext(request) + val resultContext = pathHandler.process(request) val response = resultContext.event.response val body = response.body diff --git a/http_server_servlet/src/main/kotlin/com/hexagonkt/http/server/servlet/ServletFilter.kt b/http_server_servlet/src/main/kotlin/com/hexagonkt/http/server/servlet/ServletFilter.kt index a5dc2d593c..4ed27d6b67 100644 --- a/http_server_servlet/src/main/kotlin/com/hexagonkt/http/server/servlet/ServletFilter.kt +++ b/http_server_servlet/src/main/kotlin/com/hexagonkt/http/server/servlet/ServletFilter.kt @@ -50,6 +50,7 @@ class ServletFilter( val handlerResponse = handlers[request.method] ?.process(ServletRequestAdapterSync(request)) + ?.response ?: HttpServerResponse() try { diff --git a/http_test/build.gradle.kts b/http_test/build.gradle.kts index 68cc7a92de..256dac7785 100644 --- a/http_test/build.gradle.kts +++ b/http_test/build.gradle.kts @@ -1,7 +1,4 @@ -import me.champeau.jmh.JMHTask -import org.jetbrains.kotlin.gradle.tasks.KotlinCompile - plugins { id("java-library") id("me.champeau.jmh") @@ -10,31 +7,10 @@ plugins { apply(from = "../gradle/kotlin.gradle") apply(from = "../gradle/publish.gradle") apply(from = "../gradle/dokka.gradle") -apply(from = "../gradle/detekt.gradle") +apply(from = "../gradle/jmh.gradle") description = "Test cases for HTTP client and server adapters." -tasks.withType { - kotlinOptions.jvmTarget = "11" -} - -tasks.withType { - val jhmVersion = properties["jhmVersion"] as? String ?: "1.36" - - jmhVersion.set(jhmVersion) - benchmarkMode.set(listOf("thrpt")) - - iterations.set(10) - batchSize.set(1) - fork.set(1) - operationsPerInvocation.set(5) - timeOnIteration.set("1s") - - warmup.set("1s") - warmupBatchSize.set(5) - warmupIterations.set(1) -} - dependencies { val junitVersion = properties["junitVersion"] val gatlingVersion = properties["gatlingVersion"] diff --git a/http_test/src/main/kotlin/com/hexagonkt/http/test/examples/SamplesTest.kt b/http_test/src/main/kotlin/com/hexagonkt/http/test/examples/SamplesTest.kt index d52e913cdb..fe80d3dbea 100644 --- a/http_test/src/main/kotlin/com/hexagonkt/http/test/examples/SamplesTest.kt +++ b/http_test/src/main/kotlin/com/hexagonkt/http/test/examples/SamplesTest.kt @@ -23,6 +23,7 @@ import com.hexagonkt.http.server.HttpServerPort import com.hexagonkt.http.server.HttpServerSettings import com.hexagonkt.http.server.callbacks.UrlCallback import com.hexagonkt.http.server.handlers.* +import com.hexagonkt.http.server.model.HttpServerRequest import com.hexagonkt.http.server.serve import com.hexagonkt.logging.slf4j.jul.Slf4jJulLoggingAdapter import org.junit.jupiter.api.AfterAll @@ -547,12 +548,12 @@ abstract class SamplesTest( // Handlers can also be tested to check predicates along the callbacks val handler = get("/path", callback) - val notFound = handler.process() - val ok = handler.process(method = GET, path = "/path") + val notFound = handler.process(HttpServerRequest()) + val ok = handler.process(HttpServerRequest(method = GET, path = "/path")) assertEquals(NOT_FOUND_404, notFound.status) assertEquals(OK_200, ok.status) - assertEquals("Callback result null null", ok.bodyString()) + assertEquals("Callback result null null", ok.response.bodyString()) // mockRequest } } diff --git a/site/build.gradle.kts b/site/build.gradle.kts index a4eee0a9fc..95952cc219 100644 --- a/site/build.gradle.kts +++ b/site/build.gradle.kts @@ -7,6 +7,7 @@ apply(from = "../gradle/kotlin.gradle") apply(from = "../gradle/icons.gradle") tasks.register("jacocoRootReport") { + dependsOn(":dokkaHtmlMultiModule") val projectExecutionData = fileTree(rootDir) { include("**/build/jacoco/*.exec") } val modulesSources = rootProject.modulesPaths("src/main/kotlin") diff --git a/site/mkdocs/index.html b/site/mkdocs/index.html index 89a6657287..14757fa211 100644 --- a/site/mkdocs/index.html +++ b/site/mkdocs/index.html @@ -20,7 +20,7 @@ Coverage - + Maven Central Repository

From 2aabe3669ca79c9a8c826830ed470f6019b97634 Mon Sep 17 00:00:00 2001 From: jaguililla Date: Thu, 9 Mar 2023 12:08:45 +0100 Subject: [PATCH 3/3] Update dependencies and improve handlers --- gradle/dokka.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/dokka.gradle b/gradle/dokka.gradle index 3289d1b403..e334dae993 100644 --- a/gradle/dokka.gradle +++ b/gradle/dokka.gradle @@ -28,7 +28,7 @@ setUpDokka(dokkaHtmlPartial) setUpDokka(dokkaJavadoc) private void setUpDokka(final Object dokkaTask) { - dokkaTask.dependsOn("compileJava", "compileKotlin") + dokkaTask.dependsOn("compileJava", "compileKotlin", "processResources") dokkaTask.moduleName.set(project.name) dokkaTask.offlineMode.set(true) dokkaTask.dokkaSourceSets {