From 5992baea7fc2f46d24a2c664fef9e3c5323ffcb1 Mon Sep 17 00:00:00 2001 From: jaguililla Date: Thu, 31 Aug 2023 12:21:29 +0200 Subject: [PATCH] Update documentation --- core/api/core.api | 8 +- .../hexagonkt/core/logging/LoggingManager.kt | 4 +- .../com/hexagonkt/core/logging/PrintLogger.kt | 16 ---- .../hexagonkt/core/logging/SystemLogger.kt | 28 +++++++ ...gingAdapter.kt => SystemLoggingAdapter.kt} | 6 +- .../core/logging/LoggingManagerTest.kt | 2 +- gradle/application.gradle | 6 +- site/mkdocs.yml | 1 + site/pages/gradle.md | 83 +++++++++++-------- site/pages/index.md | 48 ++++++----- site/pages/maven.md | 7 +- 11 files changed, 120 insertions(+), 89 deletions(-) delete mode 100644 core/src/main/kotlin/com/hexagonkt/core/logging/PrintLogger.kt create mode 100644 core/src/main/kotlin/com/hexagonkt/core/logging/SystemLogger.kt rename core/src/main/kotlin/com/hexagonkt/core/logging/{PrintLoggingAdapter.kt => SystemLoggingAdapter.kt} (78%) diff --git a/core/api/core.api b/core/api/core.api index bbccc64f2d..0e1d25e965 100644 --- a/core/api/core.api +++ b/core/api/core.api @@ -263,11 +263,11 @@ public abstract interface class com/hexagonkt/core/logging/LoggingPort { public abstract fun setLoggerLevel (Ljava/lang/String;Lcom/hexagonkt/core/logging/LoggingLevel;)V } -public final class com/hexagonkt/core/logging/PrintLogger : com/hexagonkt/core/logging/LoggerPort { +public final class com/hexagonkt/core/logging/SystemLogger : com/hexagonkt/core/logging/LoggerPort { public fun (Ljava/lang/String;)V public final fun component1 ()Ljava/lang/String; - public final fun copy (Ljava/lang/String;)Lcom/hexagonkt/core/logging/PrintLogger; - public static synthetic fun copy$default (Lcom/hexagonkt/core/logging/PrintLogger;Ljava/lang/String;ILjava/lang/Object;)Lcom/hexagonkt/core/logging/PrintLogger; + public final fun copy (Ljava/lang/String;)Lcom/hexagonkt/core/logging/SystemLogger; + public static synthetic fun copy$default (Lcom/hexagonkt/core/logging/SystemLogger;Ljava/lang/String;ILjava/lang/Object;)Lcom/hexagonkt/core/logging/SystemLogger; public fun equals (Ljava/lang/Object;)Z public final fun getName ()Ljava/lang/String; public fun hashCode ()I @@ -276,7 +276,7 @@ public final class com/hexagonkt/core/logging/PrintLogger : com/hexagonkt/core/l public fun toString ()Ljava/lang/String; } -public final class com/hexagonkt/core/logging/PrintLoggingAdapter : com/hexagonkt/core/logging/LoggingPort { +public final class com/hexagonkt/core/logging/SystemLoggingAdapter : com/hexagonkt/core/logging/LoggingPort { public fun ()V public fun (Lcom/hexagonkt/core/logging/LoggingLevel;)V public synthetic fun (Lcom/hexagonkt/core/logging/LoggingLevel;ILkotlin/jvm/internal/DefaultConstructorMarker;)V diff --git a/core/src/main/kotlin/com/hexagonkt/core/logging/LoggingManager.kt b/core/src/main/kotlin/com/hexagonkt/core/logging/LoggingManager.kt index 902c7fcaef..9532e6b604 100644 --- a/core/src/main/kotlin/com/hexagonkt/core/logging/LoggingManager.kt +++ b/core/src/main/kotlin/com/hexagonkt/core/logging/LoggingManager.kt @@ -3,11 +3,11 @@ package com.hexagonkt.core.logging import kotlin.reflect.KClass /** - * Manages Logs using [PrintLoggingAdapter] + * Manages Logs using [SystemLoggingAdapter] */ object LoggingManager { var useColor: Boolean = true - var adapter: LoggingPort = PrintLoggingAdapter() + var adapter: LoggingPort = SystemLoggingAdapter() var defaultLoggerName: String = "com.hexagonkt.core.logging" set(value) { require(value.isNotEmpty()) { "Default logger name cannot be empty string" } diff --git a/core/src/main/kotlin/com/hexagonkt/core/logging/PrintLogger.kt b/core/src/main/kotlin/com/hexagonkt/core/logging/PrintLogger.kt deleted file mode 100644 index 9b80e0072d..0000000000 --- a/core/src/main/kotlin/com/hexagonkt/core/logging/PrintLogger.kt +++ /dev/null @@ -1,16 +0,0 @@ -package com.hexagonkt.core.logging - -import com.hexagonkt.core.toText - -data class PrintLogger(val name: String) : LoggerPort { - - override fun log(level: LoggingLevel, exception: E, message: (E) -> Any?) { - if (LoggingManager.isLoggerLevelEnabled(name, level)) - println("$level $name - ${message(exception)}:\n${exception.toText()}") - } - - override fun log(level: LoggingLevel, message: () -> Any?) { - if (LoggingManager.isLoggerLevelEnabled(name, level)) - println("$level $name - ${message()}") - } -} diff --git a/core/src/main/kotlin/com/hexagonkt/core/logging/SystemLogger.kt b/core/src/main/kotlin/com/hexagonkt/core/logging/SystemLogger.kt new file mode 100644 index 0000000000..fcff7910a9 --- /dev/null +++ b/core/src/main/kotlin/com/hexagonkt/core/logging/SystemLogger.kt @@ -0,0 +1,28 @@ +package com.hexagonkt.core.logging + +import com.hexagonkt.core.logging.LoggingLevel.* + +data class SystemLogger(val name: String) : LoggerPort { + + private val logger: System.Logger = System.getLogger(name) + + override fun log(level: LoggingLevel, exception: E, message: (E) -> Any?) { + if (LoggingManager.isLoggerLevelEnabled(name, level)) + logger.log(level(level), message(exception).toString(), exception) + } + + override fun log(level: LoggingLevel, message: () -> Any?) { + if (LoggingManager.isLoggerLevelEnabled(name, level)) + logger.log(level(level), message()) + } + + private fun level(level: LoggingLevel): System.Logger.Level = + when (level) { + TRACE -> System.Logger.Level.TRACE + DEBUG -> System.Logger.Level.DEBUG + INFO -> System.Logger.Level.INFO + WARN -> System.Logger.Level.WARNING + ERROR -> System.Logger.Level.ERROR + OFF -> System.Logger.Level.OFF + } +} diff --git a/core/src/main/kotlin/com/hexagonkt/core/logging/PrintLoggingAdapter.kt b/core/src/main/kotlin/com/hexagonkt/core/logging/SystemLoggingAdapter.kt similarity index 78% rename from core/src/main/kotlin/com/hexagonkt/core/logging/PrintLoggingAdapter.kt rename to core/src/main/kotlin/com/hexagonkt/core/logging/SystemLoggingAdapter.kt index 0d17250f4e..ab9ea645ae 100644 --- a/core/src/main/kotlin/com/hexagonkt/core/logging/PrintLoggingAdapter.kt +++ b/core/src/main/kotlin/com/hexagonkt/core/logging/SystemLoggingAdapter.kt @@ -3,14 +3,12 @@ package com.hexagonkt.core.logging import com.hexagonkt.core.logging.LoggingLevel.INFO import com.hexagonkt.core.require -// TODO Wrap these loggers using System.Logger: -// https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/System.Logger.html -class PrintLoggingAdapter(defaultLevel: LoggingLevel = INFO) : LoggingPort { +class SystemLoggingAdapter(defaultLevel: LoggingLevel = INFO) : LoggingPort { private val loggerLevels: MutableMap = mutableMapOf("" to defaultLevel) override fun createLogger(name: String): LoggerPort = - PrintLogger(name) + SystemLogger(name) override fun setLoggerLevel(name: String, level: LoggingLevel) { loggerLevels[name] = level diff --git a/core/src/test/kotlin/com/hexagonkt/core/logging/LoggingManagerTest.kt b/core/src/test/kotlin/com/hexagonkt/core/logging/LoggingManagerTest.kt index 5553a857df..1d6e541cf9 100644 --- a/core/src/test/kotlin/com/hexagonkt/core/logging/LoggingManagerTest.kt +++ b/core/src/test/kotlin/com/hexagonkt/core/logging/LoggingManagerTest.kt @@ -17,7 +17,7 @@ internal class LoggingManagerTest { // TODO Repeat this test on other logging adapters @Test fun `Loggers are enabled and disabled at runtime`() { - LoggingManager.adapter = PrintLoggingAdapter() + LoggingManager.adapter = SystemLoggingAdapter() val allLevels = LoggingLevel.values() val ch = Logger("com.hx") diff --git a/gradle/application.gradle b/gradle/application.gradle index 3e698c560b..7f65e82c79 100644 --- a/gradle/application.gradle +++ b/gradle/application.gradle @@ -66,7 +66,7 @@ tasks.register("jpackage") { final String options = findProperty("options") final String icon = findProperty("icon") - final String modules = findProperty("modules") ?: "java.logging" + final String modules = findProperty("modules") final String jarAllName = "$name-all-${version}.jar" final java.nio.file.Path jarAll = buildDir.resolve("libs/$jarAllName") final java.nio.file.Path jpackageJar = buildDir.resolve("jpackage/$jarAllName") @@ -78,10 +78,12 @@ tasks.register("jpackage") { "--description", project.description ?: name, "--name", name, "--input", tmp.absolutePath, - "--add-modules", modules, "--main-jar", jarAllName ] + if (modules != null) + command += [ "--add-modules", modules ] + if (options != null) command += [ "--java-options", options ] diff --git a/site/mkdocs.yml b/site/mkdocs.yml index 21e9d2451f..935e6dabe9 100644 --- a/site/mkdocs.yml +++ b/site/mkdocs.yml @@ -53,6 +53,7 @@ nav: - Core: core.md - HTTP Server: http_server.md - HTTP Client: http_client.md + - Serialization: serialization.md - Templates: templates.md - Gradle Helpers: gradle.md - Maven Parent POM: maven.md diff --git a/site/pages/gradle.md b/site/pages/gradle.md index a4a01bee99..d999872f33 100644 --- a/site/pages/gradle.md +++ b/site/pages/gradle.md @@ -4,10 +4,10 @@ The build process and imported build scripts (like the ones documented here) use customize their behavior. It is possible to add/change variables of a build from the following places: -1. In the project's `gradle.properties` file. -2. In your user's gradle configuration: `~/.gradle/gradle.properties`. -3. Passing them from the command line with the following switch: `-Pkey=val`. -4. Defining a project's extra property inside `build.gradle`. Ie: `project.ext.key='val'`. +1. Passing them from the command line with the following switch: `-P key=val`. +2. In the project's `gradle.properties` file. +3. Defining a project's extra property inside `build.gradle.kts`. Ie: `project.ext["key"] = "val"`. +4. In your user's gradle configuration: `~/.gradle/gradle.properties`. For examples and reference, check [build.gradle.kts] and [gradle.properties]. @@ -20,25 +20,29 @@ These scripts can be added to your build to include a whole new capability to yo To use them, you can import the online versions, or copy them to your `gradle` directory before importing the script. -You can import these scripts by adding `apply from: $gradleScripts/$script.gradle` to your -`build.gradle` file some of them may require additional plugins inside the `plugins` section in the -root `build.gradle`. Check toolkit `build.gradle` files for examples. +You can import these scripts by adding `apply(from = "$gradleScripts/$script.gradle")` to your +`build.gradle.kts`, some of them may require additional plugins inside the `plugins` section in the +root `build.gradle.kts`. Check toolkit `build.gradle.kts` files for examples. ## Publish This script set up the project/module for publishing in [Maven Central]. It publishes all artifacts attached to the `mavenJava` publication (check [kotlin.gradle] publishing -section) at the bare minimum binaries are published. For an Open Source project, you must include -sources and javadoc. +section). + +The binaries are always published. For an Open Source project, you must also include sources and +javadoc. To use it, apply `$gradleScripts/publish.gradle`. To set up this script's parameters, check the [build variables section]. These helper settings are: -* bintrayKey (REQUIRED): if not defined will try to load BINTRAY_KEY environment variable. -* bintrayUser (REQUIRED): or BINTRAY_USER environment variable if not defined. -* license (REQUIRED): the license used in published POMs. -* vcsUrl (REQUIRED): code repository location. +* signingKey (REQUIRED): if not defined will try to load SIGNING_KEY environment variable. +* signingPassword (REQUIRED): or SIGNING_PASSWORD environment variable if not defined. +* ossrhUsername (REQUIRED): or OSSRH_USERNAME if not found. +* ossrhPassword (REQUIRED): or OSSRH_PASSWORD if not found. +* licenses (REQUIRED): the licenses used in published POMs. +* siteHost (REQUIRED): project's website. [Maven Central]: https://search.maven.org [kotlin.gradle]: https://github.com/hexagonkt/hexagon/blob/master/gradle/kotlin.gradle @@ -54,7 +58,7 @@ All modules' Markdown files are added to the documentation and test classes endi are available to be referenced as samples. To use it, apply `$gradleScripts/dokka.gradle` and add the -`id 'org.jetbrains.dokka' version 'VERSION'` plugin to the root `build.gradle`. +`id("org.jetbrains.dokka") version("VERSION")` plugin to the root `build.gradle.kts`. The format for the generated documentation will be `javadoc` to make it compatible with current IDEs. @@ -67,7 +71,7 @@ Create web icons (favicon and thumbnails for browsers/mobile) from SVG images (l For image rendering you will need [rsvg] (librsvg2-bin) and [imagemagick] installed in the development machine. -To use it, apply `$gradleScripts/icons.gradle` to your `build.gradle`. +To use it, apply `$gradleScripts/icons.gradle` to your `build.gradle.kts`. To set up this script's parameters, check the [build variables section]. These helper settings are: @@ -97,7 +101,7 @@ It sets up: - Published artifacts (binaries and sources): sourcesJar task To use it, apply `$gradleScripts/kotlin.gradle` and add the -`id 'org.jetbrains.kotlin.jvm' version 'VERSION'` plugin to the root `build.gradle`. +`id("org.jetbrains.kotlin.jvm") version("VERSION")` plugin to the root `build.gradle.kts`. To set up this script's parameters, check the [build variables section]. These helper settings are: @@ -121,17 +125,16 @@ Gradle's script for a service or application. It adds these extra tasks: * jpackage: create a jpackage distribution including a JVM with a subset of the modules. * tarJlink: compress Jpackage distribution in a single file. -To use it, apply `$gradleScripts/application.gradle` to your `build.gradle`. +To use it, apply `$gradleScripts/application.gradle` to your `build.gradle.kts`. To set up this script's parameters, check the [build variables section]. These helper settings are: -* modules: comma separated list of modules to include in the generated JRE. By default: - `java.logging,java.management`. +* modules: comma separated list of modules to include in the generated JRE. * options: JVM options passed to the jpackage generated launcher. * icon: icon to be used in the jpackage distribution. * applicationClass (REQUIRED): fully qualified name of the main class of the application. -To set up this script you need to add the main class name to your `build.gradle` file with the +To set up this script you need to add the main class name to your `build.gradle.kts` file with the following code: ```groovy @@ -163,7 +166,7 @@ The defined tasks are: * createCa: creates `ca.p12` and import its public certificate inside `trust.p12`. * createIdentities: creates the `.p12` store for all `sslDomain` variables. -To use it, apply `$gradleScripts/certificates.gradle` to your `build.gradle`. +To use it, apply `$gradleScripts/certificates.gradle` to your `build.gradle.kts`. To set up this script's parameters, check the [build variables section]. These helper settings are: @@ -186,7 +189,7 @@ To set up this script's parameters, check the [build variables section]. These h ## Lean This script changes the default Gradle source layout to be less bulky. To use it you must apply the -`$gradleScripts/lean.gradle` script to your `build.gradle` file. It must be applied after the +`$gradleScripts/lean.gradle` script to your `build.gradle.kts` file. It must be applied after the Kotlin plugin. After applying this script, the source folders will be `${projectDir}/main` and @@ -194,7 +197,7 @@ After applying this script, the source folders will be `${projectDir}/main` and ## Detekt This script sets up the build to analyze the code with the [Detekt] static code analyzer. To use it -you must apply the `$gradleScripts/detekt.gradle` script to your `build.gradle` file. It must be +you must apply the `$gradleScripts/detekt.gradle` script to your `build.gradle.kts` file. It must be applied after the Kotlin plugin. For the script to work you need to add the plugin to the plugins build section before importing the @@ -202,7 +205,7 @@ script. I.e.: ```kotlin plugins { - id("io.gitlab.arturbosch.detekt") version "VERSION" apply false + id("io.gitlab.arturbosch.detekt") version("VERSION") apply(false) } ``` @@ -223,8 +226,8 @@ The defined tasks are: * upx: compress the native executable using 'upx'. NOTE: Makes binaries use more RAM!!! * tarNative: compress native executable into a TAR file. -To use it you must apply the `$gradleScripts/native.gradle` script to your `build.gradle` file. It -must be applied after the Kotlin plugin. +To use it you must apply the `$gradleScripts/native.gradle` script to your `build.gradle.kts` file. +It must be applied after the Kotlin plugin. For the script to work you need to add the plugin to the plugins build section before importing the script. I.e.: @@ -235,22 +238,30 @@ plugins { } ``` -To add configuration metadata in your libraries. you should run these commands: +If you want to create a native image for your application you should execute: ```bash -./gradlew -Pagent build -./gradlew metadataCopy -# After including the metadata you can publish your artifacts. I.e.: -./gradlew publishToMavenLocal +./gradlew nativeCompile ``` -And if you want to create a native image for your application you should execute: +To set up this script's parameters, check the [build variables section]. These helper settings are: -```bash -./gradlew -Pagent nativeCompile +[GraalVM]: https://www.graalvm.org +[native image]: https://graalvm.github.io/native-build-tools/latest/index.html + +## JMH +Sets up the build to run JMH benchmarks. To use it you must apply the `$gradleScripts/jmh.gradle` +script to your `build.gradle.kts` file. + +For the script to work you need to add the plugin to the plugins build section before importing the +script. I.e.: + +```kotlin +plugins { + id("me.champeau.jmh") version("VERSION") apply(false) +} ``` To set up this script's parameters, check the [build variables section]. These helper settings are: -[GraalVM]: https://www.graalvm.org -[native image]: https://graalvm.github.io/native-build-tools/latest/index.html +* jmhVersion: JMH version to be used. If not specified a tested JMH version will be used. diff --git a/site/pages/index.md b/site/pages/index.md index 284de737fd..b106a57e8e 100644 --- a/site/pages/index.md +++ b/site/pages/index.md @@ -3,7 +3,7 @@ template: index.html --- The Hexagon Toolkit provides several libraries to build server applications. These libraries provide -single standalone features[^1] and are referred to as ["Ports"][Ports and Adapters Architecture]. +single standalone features and are referred to as ["Ports"][Ports and Adapters Architecture]. The main ports are: @@ -11,6 +11,8 @@ The main ports are: upload), forms processing, cookies, CORS and more. * [The HTTP client]: which supports mutual TLS, HTTP/2, WebSockets, cookies, form fields and files among other features. +* [Serialization]: provides a common way of using different data formats. Data formats are pluggable + and are handled in the same way regardless of their library. * [Template Processing]: allows template processing from URLs (local files, resources or HTTP content) binding name patterns to different engines. @@ -21,11 +23,9 @@ Hexagon is designed to fit in applications that conform to the [Hexagonal Archit [Clean Architecture], [Onion Architecture] or [Ports and Adapters Architecture]). Its design principles also fit into this architecture. -[^1]: Except the Core module that contains a set of utilities like logging. However, some of these -capacities can be replaced by other third party libraries. - [The HTTP server]: /http_server [The HTTP client]: /http_client +[Serialization]: /serialization [Template Processing]: /templates [Hexagonal Architecture]: http://fideloper.com/hexagonal-architecture [Clean Architecture]: https://8thlight.com/blog/uncle-bob/2012/08/13/the-clean-architecture.html @@ -93,16 +93,21 @@ engines. [http_client_jetty], and [http_server_jetty] are examples of this type of module. Adapter names must start with their Port name. +## Composite Port +These modules provide functionality on top of a set of ports combining them, but without relying on +any specific adapters. An example would be the [Web] module that uses [http_server] and +[template][Template Processing] Ports, but leaves clients the decision of picking the adapters they +want. + ## Library -Module that provide functionality that does not depend on different implementations, like [core]. -These modules can depend on several Ports, but never on Adapters. An example would be the [Web] -module that uses [http_server] and [template][Template Processing] Ports, but leaves clients the -decission of picking the adapters they want. +Module that provide functionality that does not depend on different implementations, like [core] and +[handlers]. ## Manager Singleton object to manage a cross toolkit aspect. I.e., Serialization, Logging or Templates. [core]: /core +[handlers]: /handlers [http_server]: /http_server [templates]: /templates @@ -111,12 +116,9 @@ Singleton object to manage a cross toolkit aspect. I.e., Serialization, Logging [http_server_jetty]: /http_server_jetty # Hexagon Extras -The libraries inside the `hexagon_extra` repository provide extra features not bound to different -implementations (rely on ports to work). They will not use dependencies outside the Hexagon -toolkit. +The libraries inside the `hexagon_extra` repository provide extra features. They may be useful to +develop applications, but not strictly required. Some of these modules are: -* [Web]: this module is meant to ease web application development. Provides helpers for - generating HTML and depends on the [HTTP Server] and [Templates] ports. * [Schedulers]: Provides repeated tasks execution based on [Cron] expressions. * [Models]: Contain classes that model common data objects. @@ -138,18 +140,19 @@ How Hexagon fits in your architecture in a picture. # Ports Ports with their provided implementations (Adapters). -| PORT | ADAPTERS | -|-------------------------|--------------------------------------------| -| [HTTP Server] | [Netty], [Netty Epoll], [Jetty], [Servlet] | -| [HTTP Client] | [Jetty][Jetty Client] | -| [Templates] | [Pebble], [FreeMarker], [Rocker] | -| [Serialization Formats] | [JSON], [YAML], [CSV], [XML], [TOML] | +| PORT | ADAPTERS | +|-------------------------|----------------------------------------------------| +| [HTTP Server] | [Netty], [Netty Epoll], [Jetty], [Servlet], [Nima] | +| [HTTP Client] | [Jetty][Jetty Client] | +| [Templates] | [Pebble], [FreeMarker], [Rocker] | +| [Serialization Formats] | [JSON], [YAML], [CSV], [XML], [TOML] | [HTTP Server]: /http_server [Netty]: /http_server_netty [Netty Epoll]: /http_server_netty_epoll [Jetty]: /http_server_jetty [Servlet]: /http_server_servlet +[Nima]: /http_server_nima [HTTP Client]: /http_client [Jetty Client]: /http_client_jetty [Templates]: /templates @@ -168,10 +171,13 @@ Module dependencies (including extra modules): ```mermaid graph TD - http_server -->|uses| http - http_client -->|uses| http + http_handlers -->|uses| http + http_handlers -->|uses| handlers + http_server -->|uses| http_handlers + http_client -->|uses| http_handlers web -->|uses| http_server web -->|uses| templates rest -->|uses| http_server rest -->|uses| serialization + rest_tools -->|uses| rest ``` diff --git a/site/pages/maven.md b/site/pages/maven.md index 4e51a55acb..a12d6067a7 100644 --- a/site/pages/maven.md +++ b/site/pages/maven.md @@ -10,11 +10,11 @@ on the directory schema you want to use): * The [lean layout POM] ## Standard Parent POM -This layout is the well-known standard one, it has more directories but its widely used. +This layout is the well-known standard one, it has more directories but its widely used. These are +the features it provides: * Set up the Kotlin plugin -* Define Hexagon dependencies' versions -* Use [JUnit 5] and [MockK] for testing +* Use [JUnit 5] and [Kotlin Test] for testing * Configure [Jacoco] coverage report ```xml @@ -47,5 +47,6 @@ using this approach is that it differs of the standard one. [lean layout POM]: https://search.maven.org/search?q=a:kotlin_lean_pom [JUnit 5]: https://junit.org/junit5 +[Kotlin Test]: https://kotlinlang.org/api/latest/kotlin.test [MockK]: https://mockk.io [Jacoco]: https://www.eclemma.org/jacoco