diff --git a/README.md b/README.md index 76ad5fb4..63461ec8 100644 --- a/README.md +++ b/README.md @@ -5,55 +5,58 @@ A collection of ready-to-use samples for [Ktor](https://ktor.io). If you're looking for older samples, please see our note on [Docs and Samples Migration](https://blog.jetbrains.com/ktor/2020/09/16/docs-and-samples-migration/). -- [Applications](#applications) -- [Server](#server) -- [Client](#client) -- [Deployment](#deployment) -- [License](#license) +- [Samples for Ktor](#samples-for-ktor) + - [Applications](#applications) + - [Server](#server) + - [Client](#client) + - [Deployment](#deployment) + - [Testing](#testing) + - [License](#license) ## Applications -* [chat](chat/README.md) - A Chat application written using [WebSockets](https://ktor.io/docs/websocket.html) and [Sessions](https://ktor.io/docs/sessions.html). -* [fullstack-mpp](fullstack-mpp/README.md) - An example of using Ktor as a client and server in a Kotlin Multiplatform +- [chat](chat/README.md) - A Chat application written using [WebSockets](https://ktor.io/docs/websocket.html) and [Sessions](https://ktor.io/docs/sessions.html). +- [fullstack-mpp](fullstack-mpp/README.md) - An example of using Ktor as a client and server in a Kotlin Multiplatform project. -* [httpbin](httpbin/README.md) - HttpBin application implementing (large parts of) [httpbin(1)](https://httpbin.org/) HTTP request & response service. -* [kweet](kweet/README.md) - A messaging application that uses [FreeMarker](https://ktor.io/docs/freemarker.html) templates and the [Locations](https://ktor.io/docs/locations.html) plugin. -* [reverse-proxy](reverse-proxy/README.md) - A simple reverse proxy application. -* [reverse-proxy-ws](reverse-proxy-ws/README.md) - A reverse proxy application written using [WebSockets](https://ktor.io/docs/websocket.html). -* [youkube](youkube/README.md) - A video upload/view application. -* [version-diff](version-diff/README.md) - An application showing the difference between artifacts in two versions of a project. -* [postgres](postgres/README.md) - An application for creating, editing and deleting articles that uses Postgres database running on Docker image as a storage. -* [mongodb](mongodb/README.md) - An application for creating, editing and deleting articles that uses Mongodb running on Docker image as a storage. -* [mvc-web](mvc-web/README.md) - An application for adding and removing wishes to wishlist that uses [FreeMarker](https://ktor.io/docs/freemarker.html) templates and Exposed. -* [opentelemetry](opentelemetry/README.md) - An application that uses Kotlin DSL to work with OpenTelemetry Ktor plugins. +- [httpbin](httpbin/README.md) - HttpBin application implementing (large parts of) [httpbin(1)](https://httpbin.org/) HTTP request & response service. +- [kweet](kweet/README.md) - A messaging application that uses [FreeMarker](https://ktor.io/docs/freemarker.html) templates and the [Locations](https://ktor.io/docs/locations.html) plugin. +- [reverse-proxy](reverse-proxy/README.md) - A simple reverse proxy application. +- [reverse-proxy-ws](reverse-proxy-ws/README.md) - A reverse proxy application written using [WebSockets](https://ktor.io/docs/websocket.html). +- [youkube](youkube/README.md) - A video upload/view application. +- [version-diff](version-diff/README.md) - An application showing the difference between artifacts in two versions of a project. +- [postgres](postgres/README.md) - An application for creating, editing and deleting articles that uses Postgres database running on Docker image as a storage. +- [mongodb](mongodb/README.md) - An application for creating, editing and deleting articles that uses Mongodb running on Docker image as a storage. +- [mvc-web](mvc-web/README.md) - An application for adding and removing wishes to wishlist that uses [FreeMarker](https://ktor.io/docs/freemarker.html) templates and Exposed. +- [opentelemetry](opentelemetry/README.md) - An application that uses Kotlin DSL to work with OpenTelemetry Ktor plugins. ## Server -* [di-kodein](di-kodein/README.md) - An application showing how to use [Kodein](https://kodein.org) +- [di-kodein](di-kodein/README.md) - An application showing how to use [Kodein](https://kodein.org) with a [Ktor](https://ktor.io) server. -* [filelisting](filelisting/README.md) - An application showing how to [serve static files](https://ktor.io/docs/serving-static-content.html). -* [location-header](location-header/README.md) - An application demonstrating how to use the HTTP `Location` +- [filelisting](filelisting/README.md) - An application showing how to [serve static files](https://ktor.io/docs/serving-static-content.html). +- [location-header](location-header/README.md) - An application demonstrating how to use the HTTP `Location` headers. -* [sse](sse/README.md) - A Server Sent Events application. -* [structured-logging](structured-logging/README.md) - An application showing how to use [Ktor](https://ktor.io) +- [sse](sse/README.md) - A Server Sent Events application. +- [structured-logging](structured-logging/README.md) - An application showing how to use [Ktor](https://ktor.io) structured logging. ## Client -* [client-mpp](client-mpp/README.md) - A sample project showing how to use a Ktor client in +- [client-mpp](client-mpp/README.md) - A sample project showing how to use a Ktor client in a [multiplatform application](https://ktor.io/docs/getting-started-ktor-client-multiplatform-mobile.html). -* [client-multipart](client-multipart/README.md) - A sample showing how to send multipart data with the HTTP client. -* [client-tools](client-tools/README.md) - A sample showing several useful extension methods not included in Ktor itself. +- [client-multipart](client-multipart/README.md) - A sample showing how to send multipart data with the HTTP client. +- [client-tools](client-tools/README.md) - A sample showing several useful extension methods not included in Ktor itself. ## Deployment -* [graalvm](graalvm/README.md) - Explains how to build and run a Ktor application in the [GraalVM](https://ktor.io/docs/graalvm.html) native image. -* [maven-google-appengine-standard](maven-google-appengine-standard/README.md) - A sample showing how to deploy Ktor +- [graalvm](graalvm/README.md) - Explains how to build and run a Ktor application in the [GraalVM](https://ktor.io/docs/graalvm.html) native image. +- [native-image-server-with-yaml-config](native-image-server-with-yaml-config/README.md) - A sample showing how to build and run a Ktor application in the GraalVM native image with a YAML configuration file. +- [maven-google-appengine-standard](maven-google-appengine-standard/README.md) - A sample showing how to deploy Ktor application to Google App Engine using [Maven](https://maven.apache.org/) and [Google App Engine](https://cloud.google.com/appengine/). ## Testing -* [jwt-auth-tests](jwt-auth-tests/README.md) - Shows how to write tests for RSA-signed JWT secured endpoints. +- [jwt-auth-tests](jwt-auth-tests/README.md) - Shows how to write tests for RSA-signed JWT secured endpoints. ## License diff --git a/native-image-server-with-yaml-config/.gitignore b/native-image-server-with-yaml-config/.gitignore new file mode 100644 index 00000000..c426c32f --- /dev/null +++ b/native-image-server-with-yaml-config/.gitignore @@ -0,0 +1,36 @@ +.gradle +build/ +!gradle/wrapper/gradle-wrapper.jar +!**/src/main/**/build/ +!**/src/test/**/build/ + +### STS ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache +bin/ +!**/src/main/**/bin/ +!**/src/test/**/bin/ + +### IntelliJ IDEA ### +.idea +*.iws +*.iml +*.ipr +out/ +!**/src/main/**/out/ +!**/src/test/**/out/ + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ + +### VS Code ### +.vscode/ \ No newline at end of file diff --git a/native-image-server-with-yaml-config/README.md b/native-image-server-with-yaml-config/README.md new file mode 100644 index 00000000..73ba625a --- /dev/null +++ b/native-image-server-with-yaml-config/README.md @@ -0,0 +1,42 @@ +# Native image server using YAML configuration file + +This example shows how to build a native image for a Ktor application using YAML confinguration and [GraalVM](https://ktor.io/docs/graalvm.html). + +## Build + +To build the application in native image, you need to execute the following command: + +```bash +./gradlew nativeCompile +``` + +## Run + +To run the application, you need to execute the following command: + +```bash +./build/native/nativeCompile/com.example.ktor-sample +``` + +The application will be running at http://0.0.0.0:8080/. + +## Update metadata + +If new dependencies are added to the project or a project has been modified, some classes may not be included in +the native image. To fix this, you need to update the metadata file. + +First you need to run the application with the agent to generate the metadata file: + +```bash +./gradlew -Pagent run +``` + +While the application is running, you need to access basic application functions + +It is important to gracefully shutdown the application to generate the metadata file. You can do this by using the [Shutdown URL](https://ktor.io/docs/server-shutdown-url.html): +url: [http://localhost:8080/shutdown](http://localhost:8080/shutdown) + +Finally, you can copy to the metadata files: +```bash +./gradlew metadataCopy --task run --dir src/main/resources/META-INF/native-image +``` diff --git a/native-image-server-with-yaml-config/build.gradle.kts b/native-image-server-with-yaml-config/build.gradle.kts new file mode 100644 index 00000000..40609908 --- /dev/null +++ b/native-image-server-with-yaml-config/build.gradle.kts @@ -0,0 +1,35 @@ + +val kotlin_version: String by project +val logback_version: String by project + +plugins { + kotlin("jvm") version "2.0.10" + id("io.ktor.plugin") version "3.0.0-beta-2" + id("org.jetbrains.kotlin.plugin.serialization") version "2.0.10" + id("org.graalvm.buildtools.native") version "0.10.2" +} + +group = "example.com" +version = "0.0.1" + +application { + mainClass.set("io.ktor.server.netty.EngineMain") + + val isDevelopment: Boolean = project.ext.has("development") + applicationDefaultJvmArgs = listOf("-Dio.ktor.development=$isDevelopment") +} + +repositories { + mavenCentral() +} + +dependencies { + implementation("io.ktor:ktor-server-content-negotiation-jvm") + implementation("io.ktor:ktor-server-core-jvm") + implementation("io.ktor:ktor-serialization-kotlinx-json-jvm") + implementation("io.ktor:ktor-server-netty-jvm") + implementation("ch.qos.logback:logback-classic:$logback_version") + implementation("io.ktor:ktor-server-config-yaml") + testImplementation("io.ktor:ktor-server-test-host-jvm") + testImplementation("org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version") +} diff --git a/native-image-server-with-yaml-config/gradle.properties b/native-image-server-with-yaml-config/gradle.properties new file mode 100644 index 00000000..95926f20 --- /dev/null +++ b/native-image-server-with-yaml-config/gradle.properties @@ -0,0 +1,4 @@ +kotlin.code.style=official +ktor_version=3.0.0-beta-2 +kotlin_version=2.0.10 +logback_version=1.4.14 diff --git a/native-image-server-with-yaml-config/gradle/wrapper/gradle-wrapper.jar b/native-image-server-with-yaml-config/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..7454180f Binary files /dev/null and b/native-image-server-with-yaml-config/gradle/wrapper/gradle-wrapper.jar differ diff --git a/native-image-server-with-yaml-config/gradle/wrapper/gradle-wrapper.properties b/native-image-server-with-yaml-config/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..e411586a --- /dev/null +++ b/native-image-server-with-yaml-config/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/native-image-server-with-yaml-config/gradlew b/native-image-server-with-yaml-config/gradlew new file mode 100755 index 00000000..1b6c7873 --- /dev/null +++ b/native-image-server-with-yaml-config/gradlew @@ -0,0 +1,234 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original 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 +# +# https://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. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +APP_NAME="Gradle" +APP_BASE_NAME=${0##*/} + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/native-image-server-with-yaml-config/gradlew.bat b/native-image-server-with-yaml-config/gradlew.bat new file mode 100644 index 00000000..107acd32 --- /dev/null +++ b/native-image-server-with-yaml-config/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/native-image-server-with-yaml-config/native-image/jni-config.json b/native-image-server-with-yaml-config/native-image/jni-config.json new file mode 100644 index 00000000..7dba6452 --- /dev/null +++ b/native-image-server-with-yaml-config/native-image/jni-config.json @@ -0,0 +1,22 @@ +[ +{ + "name":"io.ktor.server.netty.EngineMain", + "methods":[{"name":"main","parameterTypes":["java.lang.String[]"] }] +}, +{ + "name":"java.lang.Boolean", + "methods":[{"name":"getBoolean","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.lang.String", + "methods":[{"name":"lastIndexOf","parameterTypes":["int"] }, {"name":"substring","parameterTypes":["int"] }] +}, +{ + "name":"java.lang.System", + "methods":[{"name":"getProperty","parameterTypes":["java.lang.String"] }, {"name":"setProperty","parameterTypes":["java.lang.String","java.lang.String"] }] +}, +{ + "name":"sun.management.VMManagementImpl", + "fields":[{"name":"compTimeMonitoringSupport"}, {"name":"currentThreadCpuTimeSupport"}, {"name":"objectMonitorUsageSupport"}, {"name":"otherThreadCpuTimeSupport"}, {"name":"remoteDiagnosticCommandsSupport"}, {"name":"synchronizerUsageSupport"}, {"name":"threadAllocatedMemorySupport"}, {"name":"threadContentionMonitoringSupport"}] +} +] diff --git a/native-image-server-with-yaml-config/native-image/predefined-classes-config.json b/native-image-server-with-yaml-config/native-image/predefined-classes-config.json new file mode 100644 index 00000000..0e79b2c5 --- /dev/null +++ b/native-image-server-with-yaml-config/native-image/predefined-classes-config.json @@ -0,0 +1,8 @@ +[ + { + "type":"agent-extracted", + "classes":[ + ] + } +] + diff --git a/native-image-server-with-yaml-config/native-image/proxy-config.json b/native-image-server-with-yaml-config/native-image/proxy-config.json new file mode 100644 index 00000000..0d4f101c --- /dev/null +++ b/native-image-server-with-yaml-config/native-image/proxy-config.json @@ -0,0 +1,2 @@ +[ +] diff --git a/native-image-server-with-yaml-config/native-image/reflect-config.json b/native-image-server-with-yaml-config/native-image/reflect-config.json new file mode 100644 index 00000000..6e23cf32 --- /dev/null +++ b/native-image-server-with-yaml-config/native-image/reflect-config.json @@ -0,0 +1,490 @@ +[ +{ + "name":"android.os.Build$VERSION" +}, +{ + "name":"ch.qos.logback.classic.encoder.PatternLayoutEncoder", + "queryAllPublicMethods":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.classic.joran.SerializedModelConfigurator", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.classic.pattern.DateConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.classic.pattern.LevelConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.classic.pattern.LineSeparatorConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.classic.pattern.LoggerConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.classic.pattern.MessageConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.classic.pattern.ThreadConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.classic.spi.LogbackServiceProvider" +}, +{ + "name":"ch.qos.logback.classic.util.DefaultJoranConfigurator", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.core.ConsoleAppender", + "queryAllPublicMethods":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.core.OutputStreamAppender", + "methods":[{"name":"setEncoder","parameterTypes":["ch.qos.logback.core.encoder.Encoder"] }] +}, +{ + "name":"ch.qos.logback.core.encoder.Encoder", + "methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"ch.qos.logback.core.encoder.LayoutWrappingEncoder", + "methods":[{"name":"setParent","parameterTypes":["ch.qos.logback.core.spi.ContextAware"] }] +}, +{ + "name":"ch.qos.logback.core.pattern.PatternLayoutEncoderBase", + "methods":[{"name":"setPattern","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"ch.qos.logback.core.spi.ContextAware", + "methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"example.com.ApplicationKt", + "queryAllPublicMethods":true, + "methods":[{"name":"module","parameterTypes":["io.ktor.server.application.Application"] }] +}, +{ + "name":"io.ktor.http.HttpStatusCode" +}, +{ + "name":"io.ktor.http.content.TextContent" +}, +{ + "name":"io.ktor.serialization.kotlinx.json.KotlinxSerializationJsonExtensionProvider" +}, +{ + "name":"io.ktor.server.application.Application" +}, +{ + "name":"io.ktor.server.config.HoconConfigLoader" +}, +{ + "name":"io.ktor.server.config.yaml.YamlConfigLoader" +}, +{ + "name":"io.ktor.server.netty.NettyApplicationCall", + "fields":[{"name":"messageReleased"}] +}, +{ + "name":"io.ktor.server.netty.NettyApplicationCallHandler", + "methods":[{"name":"channelRead","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object"] }, {"name":"exceptionCaught","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Throwable"] }] +}, +{ + "name":"io.ktor.server.netty.NettyChannelInitializer" +}, +{ + "name":"io.ktor.server.netty.NettyHttpHandlerState", + "fields":[{"name":"activeRequests$internal"}, {"name":"isChannelReadCompleted$internal"}, {"name":"isCurrentRequestFullyRead$internal"}, {"name":"skippedRead$internal"}] +}, +{ + "name":"io.ktor.server.netty.cio.NettyHttpResponsePipeline", + "fields":[{"name":"isDataNotFlushed"}] +}, +{ + "name":"io.ktor.server.netty.cio.RequestBodyHandler", + "fields":[{"name":"buffersInProcessingCount"}], + "methods":[{"name":"channelRead","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object"] }, {"name":"exceptionCaught","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Throwable"] }] +}, +{ + "name":"io.ktor.server.netty.http1.NettyHttp1Handler", + "methods":[{"name":"channelActive","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelInactive","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelRead","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object"] }, {"name":"channelReadComplete","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"exceptionCaught","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Throwable"] }] +}, +{ + "name":"io.ktor.util.collections.CopyOnWriteHashMap", + "fields":[{"name":"current"}] +}, +{ + "name":"io.ktor.util.internal.LockFreeLinkedListNode", + "fields":[{"name":"_next"}, {"name":"_prev"}, {"name":"_removedRef"}] +}, +{ + "name":"io.netty.bootstrap.ServerBootstrap$1" +}, +{ + "name":"io.netty.bootstrap.ServerBootstrap$ServerBootstrapAcceptor", + "methods":[{"name":"channelRead","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object"] }, {"name":"exceptionCaught","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Throwable"] }] +}, +{ + "name":"io.netty.buffer.AbstractByteBufAllocator", + "queryAllDeclaredMethods":true +}, +{ + "name":"io.netty.buffer.AbstractReferenceCountedByteBuf", + "fields":[{"name":"refCnt"}] +}, +{ + "name":"io.netty.channel.AbstractChannelHandlerContext", + "fields":[{"name":"handlerState"}] +}, +{ + "name":"io.netty.channel.ChannelHandlerAdapter", + "methods":[{"name":"exceptionCaught","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Throwable"] }] +}, +{ + "name":"io.netty.channel.ChannelInboundHandlerAdapter", + "methods":[{"name":"channelActive","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelInactive","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelRead","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object"] }, {"name":"channelReadComplete","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelRegistered","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelUnregistered","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelWritabilityChanged","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"exceptionCaught","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Throwable"] }, {"name":"userEventTriggered","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object"] }] +}, +{ + "name":"io.netty.channel.ChannelInitializer", + "methods":[{"name":"channelRegistered","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"exceptionCaught","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Throwable"] }] +}, +{ + "name":"io.netty.channel.ChannelOutboundBuffer", + "fields":[{"name":"totalPendingSize"}, {"name":"unwritable"}] +}, +{ + "name":"io.netty.channel.ChannelOutboundHandlerAdapter", + "methods":[{"name":"bind","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.net.SocketAddress","io.netty.channel.ChannelPromise"] }, {"name":"close","parameterTypes":["io.netty.channel.ChannelHandlerContext","io.netty.channel.ChannelPromise"] }, {"name":"connect","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.net.SocketAddress","java.net.SocketAddress","io.netty.channel.ChannelPromise"] }, {"name":"deregister","parameterTypes":["io.netty.channel.ChannelHandlerContext","io.netty.channel.ChannelPromise"] }, {"name":"disconnect","parameterTypes":["io.netty.channel.ChannelHandlerContext","io.netty.channel.ChannelPromise"] }, {"name":"flush","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"read","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }] +}, +{ + "name":"io.netty.channel.CombinedChannelDuplexHandler", + "methods":[{"name":"bind","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.net.SocketAddress","io.netty.channel.ChannelPromise"] }, {"name":"channelActive","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelInactive","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelRead","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object"] }, {"name":"channelReadComplete","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelRegistered","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelUnregistered","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelWritabilityChanged","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"close","parameterTypes":["io.netty.channel.ChannelHandlerContext","io.netty.channel.ChannelPromise"] }, {"name":"connect","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.net.SocketAddress","java.net.SocketAddress","io.netty.channel.ChannelPromise"] }, {"name":"deregister","parameterTypes":["io.netty.channel.ChannelHandlerContext","io.netty.channel.ChannelPromise"] }, {"name":"disconnect","parameterTypes":["io.netty.channel.ChannelHandlerContext","io.netty.channel.ChannelPromise"] }, {"name":"exceptionCaught","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Throwable"] }, {"name":"flush","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"read","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"userEventTriggered","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object"] }, {"name":"write","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object","io.netty.channel.ChannelPromise"] }] +}, +{ + "name":"io.netty.channel.DefaultChannelConfig", + "fields":[{"name":"autoRead"}, {"name":"writeBufferWaterMark"}] +}, +{ + "name":"io.netty.channel.DefaultChannelPipeline", + "fields":[{"name":"estimatorHandle"}] +}, +{ + "name":"io.netty.channel.DefaultChannelPipeline$HeadContext", + "methods":[{"name":"bind","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.net.SocketAddress","io.netty.channel.ChannelPromise"] }, {"name":"channelActive","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelInactive","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelRead","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object"] }, {"name":"channelReadComplete","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelRegistered","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelUnregistered","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelWritabilityChanged","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"close","parameterTypes":["io.netty.channel.ChannelHandlerContext","io.netty.channel.ChannelPromise"] }, {"name":"connect","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.net.SocketAddress","java.net.SocketAddress","io.netty.channel.ChannelPromise"] }, {"name":"deregister","parameterTypes":["io.netty.channel.ChannelHandlerContext","io.netty.channel.ChannelPromise"] }, {"name":"disconnect","parameterTypes":["io.netty.channel.ChannelHandlerContext","io.netty.channel.ChannelPromise"] }, {"name":"exceptionCaught","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Throwable"] }, {"name":"flush","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"read","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"userEventTriggered","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object"] }, {"name":"write","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object","io.netty.channel.ChannelPromise"] }] +}, +{ + "name":"io.netty.channel.DefaultChannelPipeline$TailContext", + "methods":[{"name":"channelActive","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelInactive","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelRead","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object"] }, {"name":"channelReadComplete","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelRegistered","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelUnregistered","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelWritabilityChanged","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"exceptionCaught","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Throwable"] }, {"name":"userEventTriggered","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object"] }] +}, +{ + "name":"io.netty.channel.DefaultFileRegion" +}, +{ + "name":"io.netty.channel.epoll.NativeDatagramPacketArray$NativeDatagramPacket" +}, +{ + "name":"io.netty.channel.socket.nio.NioServerSocketChannel", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"io.netty.channel.unix.PeerCredentials" +}, +{ + "name":"io.netty.handler.codec.http.HttpServerCodec" +}, +{ + "name":"io.netty.handler.codec.http.HttpServerExpectContinueHandler", + "methods":[{"name":"channelRead","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object"] }] +}, +{ + "name":"io.netty.handler.timeout.WriteTimeoutHandler", + "methods":[{"name":"write","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object","io.netty.channel.ChannelPromise"] }] +}, +{ + "name":"io.netty.util.AbstractReferenceCounted", + "fields":[{"name":"refCnt"}] +}, +{ + "name":"io.netty.util.DefaultAttributeMap", + "fields":[{"name":"attributes"}] +}, +{ + "name":"io.netty.util.Recycler$DefaultHandle", + "fields":[{"name":"state"}] +}, +{ + "name":"io.netty.util.ReferenceCountUtil", + "queryAllDeclaredMethods":true +}, +{ + "name":"io.netty.util.concurrent.DefaultPromise", + "fields":[{"name":"result"}] +}, +{ + "name":"io.netty.util.concurrent.SingleThreadEventExecutor", + "fields":[{"name":"state"}, {"name":"threadProperties"}] +}, +{ + "name":"io.netty.util.internal.NativeLibraryUtil", + "methods":[{"name":"loadLibrary","parameterTypes":["java.lang.String","boolean"] }] +}, +{ + "name":"io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueColdProducerFields", + "fields":[{"name":"producerLimit"}] +}, +{ + "name":"io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueConsumerFields", + "fields":[{"name":"consumerIndex"}] +}, +{ + "name":"io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueProducerFields", + "fields":[{"name":"producerIndex"}] +}, +{ + "name":"io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueConsumerIndexField", + "fields":[{"name":"consumerIndex"}] +}, +{ + "name":"io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerIndexField", + "fields":[{"name":"producerIndex"}] +}, +{ + "name":"io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerLimitField", + "fields":[{"name":"producerLimit"}] +}, +{ + "name":"java.io.FileDescriptor" +}, +{ + "name":"java.io.FilePermission" +}, +{ + "name":"java.lang.ClassValue" +}, +{ + "name":"java.lang.ProcessHandle", + "methods":[{"name":"current","parameterTypes":[] }, {"name":"pid","parameterTypes":[] }] +}, +{ + "name":"java.lang.RuntimePermission" +}, +{ + "name":"java.lang.String", + "allDeclaredClasses":true, + "fields":[{"name":"Companion"}] +}, +{ + "name":"java.lang.Thread", + "fields":[{"name":"threadLocalRandomProbe"}] +}, +{ + "name":"java.lang.management.ManagementFactory", + "methods":[{"name":"getRuntimeMXBean","parameterTypes":[] }] +}, +{ + "name":"java.lang.management.RuntimeMXBean", + "methods":[{"name":"getInputArguments","parameterTypes":[] }] +}, +{ + "name":"java.net.NetPermission" +}, +{ + "name":"java.net.SocketPermission" +}, +{ + "name":"java.net.URLPermission", + "methods":[{"name":"","parameterTypes":["java.lang.String","java.lang.String"] }] +}, +{ + "name":"java.nio.Bits", + "methods":[{"name":"unaligned","parameterTypes":[] }] +}, +{ + "name":"java.nio.Buffer", + "fields":[{"name":"address"}] +}, +{ + "name":"java.nio.ByteBuffer", + "methods":[{"name":"alignedSlice","parameterTypes":["int"] }] +}, +{ + "name":"java.nio.DirectByteBuffer", + "methods":[{"name":"","parameterTypes":["long","long"] }] +}, +{ + "name":"java.nio.channels.FileChannel" +}, +{ + "name":"java.nio.channels.spi.SelectorProvider", + "methods":[{"name":"openServerSocketChannel","parameterTypes":["java.net.ProtocolFamily"] }, {"name":"openSocketChannel","parameterTypes":["java.net.ProtocolFamily"] }] +}, +{ + "name":"java.security.AllPermission" +}, +{ + "name":"java.security.SecurityPermission" +}, +{ + "name":"java.util.Map" +}, +{ + "name":"java.util.PropertyPermission" +}, +{ + "name":"java.util.concurrent.ScheduledThreadPoolExecutor", + "methods":[{"name":"setRemoveOnCancelPolicy","parameterTypes":["boolean"] }] +}, +{ + "name":"java.util.concurrent.atomic.AtomicBoolean", + "fields":[{"name":"value"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicReference", + "fields":[{"name":"value"}] +}, +{ + "name":"java.util.concurrent.atomic.Striped64", + "fields":[{"name":"base"}, {"name":"cellsBusy"}] +}, +{ + "name":"java.util.concurrent.atomic.Striped64$Cell", + "fields":[{"name":"value"}] +}, +{ + "name":"javax.smartcardio.CardPermission" +}, +{ + "name":"jdk.internal.misc.Unsafe", + "methods":[{"name":"getUnsafe","parameterTypes":[] }] +}, +{ + "name":"kotlin.Array" +}, +{ + "name":"kotlin.Metadata", + "queryAllDeclaredMethods":true, + "methods":[{"name":"bv","parameterTypes":[] }, {"name":"d1","parameterTypes":[] }, {"name":"d2","parameterTypes":[] }, {"name":"k","parameterTypes":[] }, {"name":"mv","parameterTypes":[] }, {"name":"pn","parameterTypes":[] }, {"name":"xi","parameterTypes":[] }, {"name":"xs","parameterTypes":[] }] +}, +{ + "name":"kotlin.SafePublicationLazyImpl", + "fields":[{"name":"_value"}] +}, +{ + "name":"kotlin.String" +}, +{ + "name":"kotlin.Unit" +}, +{ + "name":"kotlin.collections.Map" +}, +{ + "name":"kotlin.jvm.internal.DefaultConstructorMarker" +}, +{ + "name":"kotlin.reflect.jvm.internal.ReflectionFactoryImpl", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"kotlin.reflect.jvm.internal.impl.load.java.ErasedOverridabilityCondition" +}, +{ + "name":"kotlin.reflect.jvm.internal.impl.load.java.FieldOverridabilityCondition" +}, +{ + "name":"kotlin.reflect.jvm.internal.impl.load.java.JavaIncompatibilityRulesOverridabilityCondition" +}, +{ + "name":"kotlin.reflect.jvm.internal.impl.resolve.scopes.DescriptorKindFilter", + "allPublicFields":true +}, +{ + "name":"kotlinx.coroutines.CancellableContinuationImpl", + "fields":[{"name":"_decisionAndIndex$volatile"}, {"name":"_parentHandle$volatile"}, {"name":"_state$volatile"}] +}, +{ + "name":"kotlinx.coroutines.CompletedExceptionally", + "fields":[{"name":"_handled$volatile"}] +}, +{ + "name":"kotlinx.coroutines.EventLoopImplBase", + "fields":[{"name":"_delayed$volatile"}, {"name":"_isCompleted$volatile"}, {"name":"_queue$volatile"}] +}, +{ + "name":"kotlinx.coroutines.JobSupport", + "fields":[{"name":"_parentHandle$volatile"}, {"name":"_state$volatile"}] +}, +{ + "name":"kotlinx.coroutines.JobSupport$Finishing", + "fields":[{"name":"_exceptionsHolder$volatile"}, {"name":"_isCompleting$volatile"}, {"name":"_rootCause$volatile"}] +}, +{ + "name":"kotlinx.coroutines.channels.BufferedChannel", + "fields":[{"name":"_closeCause$volatile"}, {"name":"bufferEnd$volatile"}, {"name":"bufferEndSegment$volatile"}, {"name":"closeHandler$volatile"}, {"name":"completedExpandBuffersAndPauseFlag$volatile"}, {"name":"receiveSegment$volatile"}, {"name":"receivers$volatile"}, {"name":"sendSegment$volatile"}, {"name":"sendersAndCloseStatus$volatile"}] +}, +{ + "name":"kotlinx.coroutines.internal.ConcurrentLinkedListNode", + "fields":[{"name":"_next$volatile"}, {"name":"_prev$volatile"}] +}, +{ + "name":"kotlinx.coroutines.internal.DispatchedContinuation", + "fields":[{"name":"_reusableCancellableContinuation$volatile"}] +}, +{ + "name":"kotlinx.coroutines.internal.LimitedDispatcher", + "fields":[{"name":"runningWorkers$volatile"}] +}, +{ + "name":"kotlinx.coroutines.internal.LockFreeLinkedListNode", + "fields":[{"name":"_next$volatile"}, {"name":"_prev$volatile"}, {"name":"_removedRef$volatile"}] +}, +{ + "name":"kotlinx.coroutines.internal.LockFreeTaskQueue", + "fields":[{"name":"_cur$volatile"}] +}, +{ + "name":"kotlinx.coroutines.internal.LockFreeTaskQueueCore", + "fields":[{"name":"_next$volatile"}, {"name":"_state$volatile"}] +}, +{ + "name":"kotlinx.coroutines.internal.Segment", + "fields":[{"name":"cleanedAndPointers$volatile"}] +}, +{ + "name":"kotlinx.coroutines.scheduling.CoroutineScheduler", + "fields":[{"name":"_isTerminated$volatile"}, {"name":"controlState$volatile"}, {"name":"parkedWorkersStack$volatile"}] +}, +{ + "name":"kotlinx.coroutines.scheduling.CoroutineScheduler$Worker", + "fields":[{"name":"workerCtl$volatile"}] +}, +{ + "name":"kotlinx.coroutines.scheduling.WorkQueue", + "fields":[{"name":"blockingTasksInBuffer$volatile"}, {"name":"consumerIndex$volatile"}, {"name":"lastScheduledTask$volatile"}, {"name":"producerIndex$volatile"}] +}, +{ + "name":"sun.misc.Unsafe", + "fields":[{"name":"theUnsafe"}], + "methods":[{"name":"addressSize","parameterTypes":[] }, {"name":"allocateMemory","parameterTypes":["long"] }, {"name":"arrayBaseOffset","parameterTypes":["java.lang.Class"] }, {"name":"arrayIndexScale","parameterTypes":["java.lang.Class"] }, {"name":"copyMemory","parameterTypes":["java.lang.Object","long","java.lang.Object","long","long"] }, {"name":"freeMemory","parameterTypes":["long"] }, {"name":"getAndAddLong","parameterTypes":["java.lang.Object","long","long"] }, {"name":"getAndSetObject","parameterTypes":["java.lang.Object","long","java.lang.Object"] }, {"name":"getBoolean","parameterTypes":["java.lang.Object","long"] }, {"name":"getByte","parameterTypes":["long"] }, {"name":"getByte","parameterTypes":["java.lang.Object","long"] }, {"name":"getInt","parameterTypes":["long"] }, {"name":"getInt","parameterTypes":["java.lang.Object","long"] }, {"name":"getLong","parameterTypes":["long"] }, {"name":"getLong","parameterTypes":["java.lang.Object","long"] }, {"name":"invokeCleaner","parameterTypes":["java.nio.ByteBuffer"] }, {"name":"objectFieldOffset","parameterTypes":["java.lang.reflect.Field"] }, {"name":"putByte","parameterTypes":["long","byte"] }, {"name":"putByte","parameterTypes":["java.lang.Object","long","byte"] }, {"name":"putInt","parameterTypes":["long","int"] }, {"name":"putInt","parameterTypes":["java.lang.Object","long","int"] }, {"name":"putLong","parameterTypes":["long","long"] }, {"name":"putLong","parameterTypes":["java.lang.Object","long","long"] }, {"name":"reallocateMemory","parameterTypes":["long","long"] }, {"name":"setMemory","parameterTypes":["long","long","byte"] }, {"name":"setMemory","parameterTypes":["java.lang.Object","long","long","byte"] }, {"name":"staticFieldBase","parameterTypes":["java.lang.reflect.Field"] }, {"name":"staticFieldOffset","parameterTypes":["java.lang.reflect.Field"] }, {"name":"storeFence","parameterTypes":[] }] +}, +{ + "name":"sun.misc.VM" +}, +{ + "name":"sun.nio.ch.SelectorImpl", + "fields":[{"name":"publicSelectedKeys"}, {"name":"selectedKeys"}] +} +] diff --git a/native-image-server-with-yaml-config/native-image/resource-config.json b/native-image-server-with-yaml-config/native-image/resource-config.json new file mode 100644 index 00000000..7a2bd667 --- /dev/null +++ b/native-image-server-with-yaml-config/native-image/resource-config.json @@ -0,0 +1,52 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\QMETA-INF/native/libnetty_transport_native_kqueue.dylib\\E" + }, { + "pattern":"\\QMETA-INF/native/libnetty_transport_native_kqueue.jnilib\\E" + }, { + "pattern":"\\QMETA-INF/native/libnetty_transport_native_kqueue_aarch_64.dylib\\E" + }, { + "pattern":"\\QMETA-INF/native/libnetty_transport_native_kqueue_aarch_64.jnilib\\E" + }, { + "pattern":"\\QMETA-INF/services/ch.qos.logback.classic.spi.Configurator\\E" + }, { + "pattern":"\\QMETA-INF/services/io.ktor.serialization.kotlinx.KotlinxSerializationExtensionProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/io.ktor.server.config.ConfigLoader\\E" + }, { + "pattern":"\\QMETA-INF/services/java.lang.System$LoggerFinder\\E" + }, { + "pattern":"\\QMETA-INF/services/java.nio.channels.spi.SelectorProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/java.time.zone.ZoneRulesProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/javax.xml.parsers.SAXParserFactory\\E" + }, { + "pattern":"\\QMETA-INF/services/kotlin.reflect.jvm.internal.impl.resolve.ExternalOverridabilityCondition\\E" + }, { + "pattern":"\\QMETA-INF/services/kotlin.reflect.jvm.internal.impl.util.ModuleVisibilityHelper\\E" + }, { + "pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E" + }, { + "pattern":"\\Qapplication.yaml\\E" + }, { + "pattern":"\\Qkotlin/collections/collections.kotlin_builtins\\E" + }, { + "pattern":"\\Qkotlin/kotlin.kotlin_builtins\\E" + }, { + "pattern":"\\Qlogback-test.scmo\\E" + }, { + "pattern":"\\Qlogback-test.xml\\E" + }, { + "pattern":"\\Qlogback.scmo\\E" + }, { + "pattern":"\\Qlogback.xml\\E" + }, { + "pattern":"java.xml:\\Qjdk/xml/internal/jdkcatalog/JDKCatalog.xml\\E" + }]}, + "bundles":[{ + "name":"sun.util.resources.cldr.CalendarData", + "locales":["und"] + }] +} diff --git a/native-image-server-with-yaml-config/native-image/serialization-config.json b/native-image-server-with-yaml-config/native-image/serialization-config.json new file mode 100644 index 00000000..f3d7e06e --- /dev/null +++ b/native-image-server-with-yaml-config/native-image/serialization-config.json @@ -0,0 +1,8 @@ +{ + "types":[ + ], + "lambdaCapturingTypes":[ + ], + "proxies":[ + ] +} diff --git a/native-image-server-with-yaml-config/settings.gradle.kts b/native-image-server-with-yaml-config/settings.gradle.kts new file mode 100644 index 00000000..8e72c22c --- /dev/null +++ b/native-image-server-with-yaml-config/settings.gradle.kts @@ -0,0 +1 @@ +rootProject.name = "ktor-native-image-server-with-config" diff --git a/native-image-server-with-yaml-config/src/main/kotlin/example/com/Application.kt b/native-image-server-with-yaml-config/src/main/kotlin/example/com/Application.kt new file mode 100644 index 00000000..89990bc1 --- /dev/null +++ b/native-image-server-with-yaml-config/src/main/kotlin/example/com/Application.kt @@ -0,0 +1,13 @@ +package example.com + +import example.com.plugins.* +import io.ktor.server.application.* + +fun main(args: Array) { + io.ktor.server.netty.EngineMain.main(args) +} + +fun Application.module() { + configureSerialization() + configureRouting() +} diff --git a/native-image-server-with-yaml-config/src/main/kotlin/example/com/plugins/Routing.kt b/native-image-server-with-yaml-config/src/main/kotlin/example/com/plugins/Routing.kt new file mode 100644 index 00000000..535fa098 --- /dev/null +++ b/native-image-server-with-yaml-config/src/main/kotlin/example/com/plugins/Routing.kt @@ -0,0 +1,14 @@ +package example.com.plugins + +import io.ktor.server.application.* +import io.ktor.server.engine.* +import io.ktor.server.response.* +import io.ktor.server.routing.* + +fun Application.configureRouting() { + routing { + get("/") { + call.respondText("Hello World!") + } + } +} diff --git a/native-image-server-with-yaml-config/src/main/kotlin/example/com/plugins/Serialization.kt b/native-image-server-with-yaml-config/src/main/kotlin/example/com/plugins/Serialization.kt new file mode 100644 index 00000000..51d19f54 --- /dev/null +++ b/native-image-server-with-yaml-config/src/main/kotlin/example/com/plugins/Serialization.kt @@ -0,0 +1,18 @@ +package example.com.plugins + +import io.ktor.serialization.kotlinx.json.* +import io.ktor.server.application.* +import io.ktor.server.plugins.contentnegotiation.* +import io.ktor.server.response.* +import io.ktor.server.routing.* + +fun Application.configureSerialization() { + install(ContentNegotiation) { + json() + } + routing { + get("/json/kotlinx-serialization") { + call.respond(mapOf("hello" to "world")) + } + } +} diff --git a/native-image-server-with-yaml-config/src/main/resources/META-INF/native-image/jni-config.json b/native-image-server-with-yaml-config/src/main/resources/META-INF/native-image/jni-config.json new file mode 100644 index 00000000..39e21f49 --- /dev/null +++ b/native-image-server-with-yaml-config/src/main/resources/META-INF/native-image/jni-config.json @@ -0,0 +1,22 @@ +[ +{ + "name":"io.ktor.server.netty.EngineMain", + "methods":[{"name":"main","parameterTypes":["java.lang.String[]"] }] +}, +{ + "name":"java.lang.Boolean", + "methods":[{"name":"getBoolean","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"java.lang.String", + "methods":[{"name":"lastIndexOf","parameterTypes":["int"] }, {"name":"substring","parameterTypes":["int"] }] +}, +{ + "name":"java.lang.System", + "methods":[{"name":"getProperty","parameterTypes":["java.lang.String"] }, {"name":"setProperty","parameterTypes":["java.lang.String","java.lang.String"] }] +}, +{ + "name":"sun.management.VMManagementImpl", + "fields":[{"name":"compTimeMonitoringSupport"}, {"name":"currentThreadCpuTimeSupport"}, {"name":"objectMonitorUsageSupport"}, {"name":"otherThreadCpuTimeSupport"}, {"name":"remoteDiagnosticCommandsSupport"}, {"name":"synchronizerUsageSupport"}, {"name":"threadAllocatedMemorySupport"}, {"name":"threadContentionMonitoringSupport"}] +} +] \ No newline at end of file diff --git a/native-image-server-with-yaml-config/src/main/resources/META-INF/native-image/predefined-classes-config.json b/native-image-server-with-yaml-config/src/main/resources/META-INF/native-image/predefined-classes-config.json new file mode 100644 index 00000000..84789507 --- /dev/null +++ b/native-image-server-with-yaml-config/src/main/resources/META-INF/native-image/predefined-classes-config.json @@ -0,0 +1,7 @@ +[ + { + "type":"agent-extracted", + "classes":[ + ] + } +] diff --git a/native-image-server-with-yaml-config/src/main/resources/META-INF/native-image/proxy-config.json b/native-image-server-with-yaml-config/src/main/resources/META-INF/native-image/proxy-config.json new file mode 100644 index 00000000..32960f8c --- /dev/null +++ b/native-image-server-with-yaml-config/src/main/resources/META-INF/native-image/proxy-config.json @@ -0,0 +1,2 @@ +[ +] \ No newline at end of file diff --git a/native-image-server-with-yaml-config/src/main/resources/META-INF/native-image/reflect-config.json b/native-image-server-with-yaml-config/src/main/resources/META-INF/native-image/reflect-config.json new file mode 100644 index 00000000..7f1eb478 --- /dev/null +++ b/native-image-server-with-yaml-config/src/main/resources/META-INF/native-image/reflect-config.json @@ -0,0 +1,494 @@ +[ +{ + "name":"android.os.Build$VERSION" +}, +{ + "name":"ch.qos.logback.classic.encoder.PatternLayoutEncoder", + "queryAllPublicMethods":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.classic.joran.SerializedModelConfigurator", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.classic.pattern.DateConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.classic.pattern.LevelConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.classic.pattern.LineSeparatorConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.classic.pattern.LoggerConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.classic.pattern.MessageConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.classic.pattern.ThreadConverter", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.classic.spi.LogbackServiceProvider" +}, +{ + "name":"ch.qos.logback.classic.util.DefaultJoranConfigurator", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.core.ConsoleAppender", + "queryAllPublicMethods":true, + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"ch.qos.logback.core.OutputStreamAppender", + "methods":[{"name":"setEncoder","parameterTypes":["ch.qos.logback.core.encoder.Encoder"] }] +}, +{ + "name":"ch.qos.logback.core.encoder.Encoder", + "methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"ch.qos.logback.core.encoder.LayoutWrappingEncoder", + "methods":[{"name":"setParent","parameterTypes":["ch.qos.logback.core.spi.ContextAware"] }] +}, +{ + "name":"ch.qos.logback.core.pattern.PatternLayoutEncoderBase", + "methods":[{"name":"setPattern","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"ch.qos.logback.core.spi.ContextAware", + "methods":[{"name":"valueOf","parameterTypes":["java.lang.String"] }] +}, +{ + "name":"com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"example.com.ApplicationKt", + "queryAllPublicMethods":true, + "methods":[{"name":"module","parameterTypes":["io.ktor.server.application.Application"] }] +}, +{ + "name":"io.ktor.http.HttpStatusCode" +}, +{ + "name":"io.ktor.http.content.TextContent" +}, +{ + "name":"io.ktor.serialization.kotlinx.json.KotlinxSerializationJsonExtensionProvider" +}, +{ + "name":"io.ktor.server.application.Application" +}, +{ + "name":"io.ktor.server.config.HoconConfigLoader" +}, +{ + "name":"io.ktor.server.config.yaml.YamlConfigLoader" +}, +{ + "name":"io.ktor.server.netty.NettyApplicationCall", + "fields":[{"name":"messageReleased"}] +}, +{ + "name":"io.ktor.server.netty.NettyApplicationCallHandler", + "methods":[{"name":"channelRead","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object"] }, {"name":"exceptionCaught","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Throwable"] }] +}, +{ + "name":"io.ktor.server.netty.NettyChannelInitializer" +}, +{ + "name":"io.ktor.server.netty.NettyHttpHandlerState", + "fields":[{"name":"activeRequests$internal"}, {"name":"isChannelReadCompleted$internal"}, {"name":"isCurrentRequestFullyRead$internal"}, {"name":"skippedRead$internal"}] +}, +{ + "name":"io.ktor.server.netty.cio.NettyHttpResponsePipeline", + "fields":[{"name":"isDataNotFlushed"}] +}, +{ + "name":"io.ktor.server.netty.cio.RequestBodyHandler", + "fields":[{"name":"buffersInProcessingCount"}], + "methods":[{"name":"channelRead","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object"] }, {"name":"exceptionCaught","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Throwable"] }] +}, +{ + "name":"io.ktor.server.netty.http1.NettyHttp1Handler", + "methods":[{"name":"channelActive","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelInactive","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelRead","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object"] }, {"name":"channelReadComplete","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"exceptionCaught","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Throwable"] }] +}, +{ + "name":"io.ktor.util.collections.CopyOnWriteHashMap", + "fields":[{"name":"current"}] +}, +{ + "name":"io.ktor.util.internal.LockFreeLinkedListNode", + "fields":[{"name":"_next"}, {"name":"_prev"}, {"name":"_removedRef"}] +}, +{ + "name":"io.netty.bootstrap.ServerBootstrap$1" +}, +{ + "name":"io.netty.bootstrap.ServerBootstrap$ServerBootstrapAcceptor", + "methods":[{"name":"channelRead","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object"] }, {"name":"exceptionCaught","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Throwable"] }] +}, +{ + "name":"io.netty.buffer.AbstractByteBufAllocator", + "queryAllDeclaredMethods":true +}, +{ + "name":"io.netty.buffer.AbstractReferenceCountedByteBuf", + "fields":[{"name":"refCnt"}] +}, +{ + "name":"io.netty.channel.AbstractChannelHandlerContext", + "fields":[{"name":"handlerState"}] +}, +{ + "name":"io.netty.channel.ChannelHandlerAdapter", + "methods":[{"name":"exceptionCaught","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Throwable"] }] +}, +{ + "name":"io.netty.channel.ChannelInboundHandlerAdapter", + "methods":[{"name":"channelActive","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelInactive","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelRead","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object"] }, {"name":"channelReadComplete","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelRegistered","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelUnregistered","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelWritabilityChanged","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"exceptionCaught","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Throwable"] }, {"name":"userEventTriggered","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object"] }] +}, +{ + "name":"io.netty.channel.ChannelInitializer", + "methods":[{"name":"channelRegistered","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"exceptionCaught","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Throwable"] }] +}, +{ + "name":"io.netty.channel.ChannelOutboundBuffer", + "fields":[{"name":"totalPendingSize"}, {"name":"unwritable"}] +}, +{ + "name":"io.netty.channel.ChannelOutboundHandlerAdapter", + "methods":[{"name":"bind","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.net.SocketAddress","io.netty.channel.ChannelPromise"] }, {"name":"close","parameterTypes":["io.netty.channel.ChannelHandlerContext","io.netty.channel.ChannelPromise"] }, {"name":"connect","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.net.SocketAddress","java.net.SocketAddress","io.netty.channel.ChannelPromise"] }, {"name":"deregister","parameterTypes":["io.netty.channel.ChannelHandlerContext","io.netty.channel.ChannelPromise"] }, {"name":"disconnect","parameterTypes":["io.netty.channel.ChannelHandlerContext","io.netty.channel.ChannelPromise"] }, {"name":"flush","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"read","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }] +}, +{ + "name":"io.netty.channel.CombinedChannelDuplexHandler", + "methods":[{"name":"bind","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.net.SocketAddress","io.netty.channel.ChannelPromise"] }, {"name":"channelActive","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelInactive","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelRead","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object"] }, {"name":"channelReadComplete","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelRegistered","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelUnregistered","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelWritabilityChanged","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"close","parameterTypes":["io.netty.channel.ChannelHandlerContext","io.netty.channel.ChannelPromise"] }, {"name":"connect","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.net.SocketAddress","java.net.SocketAddress","io.netty.channel.ChannelPromise"] }, {"name":"deregister","parameterTypes":["io.netty.channel.ChannelHandlerContext","io.netty.channel.ChannelPromise"] }, {"name":"disconnect","parameterTypes":["io.netty.channel.ChannelHandlerContext","io.netty.channel.ChannelPromise"] }, {"name":"exceptionCaught","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Throwable"] }, {"name":"flush","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"read","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"userEventTriggered","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object"] }, {"name":"write","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object","io.netty.channel.ChannelPromise"] }] +}, +{ + "name":"io.netty.channel.DefaultChannelConfig", + "fields":[{"name":"autoRead"}, {"name":"writeBufferWaterMark"}] +}, +{ + "name":"io.netty.channel.DefaultChannelPipeline", + "fields":[{"name":"estimatorHandle"}] +}, +{ + "name":"io.netty.channel.DefaultChannelPipeline$HeadContext", + "methods":[{"name":"bind","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.net.SocketAddress","io.netty.channel.ChannelPromise"] }, {"name":"channelActive","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelInactive","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelRead","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object"] }, {"name":"channelReadComplete","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelRegistered","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelUnregistered","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelWritabilityChanged","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"close","parameterTypes":["io.netty.channel.ChannelHandlerContext","io.netty.channel.ChannelPromise"] }, {"name":"connect","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.net.SocketAddress","java.net.SocketAddress","io.netty.channel.ChannelPromise"] }, {"name":"deregister","parameterTypes":["io.netty.channel.ChannelHandlerContext","io.netty.channel.ChannelPromise"] }, {"name":"disconnect","parameterTypes":["io.netty.channel.ChannelHandlerContext","io.netty.channel.ChannelPromise"] }, {"name":"exceptionCaught","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Throwable"] }, {"name":"flush","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"read","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"userEventTriggered","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object"] }, {"name":"write","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object","io.netty.channel.ChannelPromise"] }] +}, +{ + "name":"io.netty.channel.DefaultChannelPipeline$TailContext", + "methods":[{"name":"channelActive","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelInactive","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelRead","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object"] }, {"name":"channelReadComplete","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelRegistered","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelUnregistered","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"channelWritabilityChanged","parameterTypes":["io.netty.channel.ChannelHandlerContext"] }, {"name":"exceptionCaught","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Throwable"] }, {"name":"userEventTriggered","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object"] }] +}, +{ + "name":"io.netty.channel.DefaultFileRegion" +}, +{ + "name":"io.netty.channel.epoll.NativeDatagramPacketArray$NativeDatagramPacket" +}, +{ + "name":"io.netty.channel.socket.nio.NioServerSocketChannel", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"io.netty.channel.unix.PeerCredentials" +}, +{ + "name":"io.netty.handler.codec.http.HttpServerCodec" +}, +{ + "name":"io.netty.handler.codec.http.HttpServerExpectContinueHandler", + "methods":[{"name":"channelRead","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object"] }] +}, +{ + "name":"io.netty.handler.timeout.WriteTimeoutHandler", + "methods":[{"name":"write","parameterTypes":["io.netty.channel.ChannelHandlerContext","java.lang.Object","io.netty.channel.ChannelPromise"] }] +}, +{ + "name":"io.netty.util.AbstractReferenceCounted", + "fields":[{"name":"refCnt"}] +}, +{ + "name":"io.netty.util.DefaultAttributeMap", + "fields":[{"name":"attributes"}] +}, +{ + "name":"io.netty.util.Recycler$DefaultHandle", + "fields":[{"name":"state"}] +}, +{ + "name":"io.netty.util.ReferenceCountUtil", + "queryAllDeclaredMethods":true +}, +{ + "name":"io.netty.util.concurrent.DefaultPromise", + "fields":[{"name":"result"}] +}, +{ + "name":"io.netty.util.concurrent.SingleThreadEventExecutor", + "fields":[{"name":"state"}, {"name":"threadProperties"}] +}, +{ + "name":"io.netty.util.internal.NativeLibraryUtil", + "methods":[{"name":"loadLibrary","parameterTypes":["java.lang.String","boolean"] }] +}, +{ + "name":"io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueColdProducerFields", + "fields":[{"name":"producerLimit"}] +}, +{ + "name":"io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueConsumerFields", + "fields":[{"name":"consumerIndex"}] +}, +{ + "name":"io.netty.util.internal.shaded.org.jctools.queues.BaseMpscLinkedArrayQueueProducerFields", + "fields":[{"name":"producerIndex"}] +}, +{ + "name":"io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueConsumerIndexField", + "fields":[{"name":"consumerIndex"}] +}, +{ + "name":"io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerIndexField", + "fields":[{"name":"producerIndex"}] +}, +{ + "name":"io.netty.util.internal.shaded.org.jctools.queues.MpscArrayQueueProducerLimitField", + "fields":[{"name":"producerLimit"}] +}, +{ + "name":"java.io.FileDescriptor" +}, +{ + "name":"java.io.FilePermission" +}, +{ + "name":"java.lang.ClassValue" +}, +{ + "name":"java.lang.ProcessHandle", + "methods":[{"name":"current","parameterTypes":[] }, {"name":"pid","parameterTypes":[] }] +}, +{ + "name":"java.lang.RuntimePermission" +}, +{ + "name":"java.lang.String", + "allDeclaredClasses":true, + "fields":[{"name":"Companion"}] +}, +{ + "name":"java.lang.Thread", + "fields":[{"name":"threadLocalRandomProbe"}] +}, +{ + "name":"java.lang.management.ManagementFactory", + "methods":[{"name":"getRuntimeMXBean","parameterTypes":[] }] +}, +{ + "name":"java.lang.management.RuntimeMXBean", + "methods":[{"name":"getInputArguments","parameterTypes":[] }] +}, +{ + "name":"java.net.NetPermission" +}, +{ + "name":"java.net.SocketPermission" +}, +{ + "name":"java.net.URLPermission", + "methods":[{"name":"","parameterTypes":["java.lang.String","java.lang.String"] }] +}, +{ + "name":"java.nio.Bits", + "methods":[{"name":"unaligned","parameterTypes":[] }] +}, +{ + "name":"java.nio.Buffer", + "fields":[{"name":"address"}] +}, +{ + "name":"java.nio.ByteBuffer", + "methods":[{"name":"alignedSlice","parameterTypes":["int"] }] +}, +{ + "name":"java.nio.DirectByteBuffer", + "methods":[{"name":"","parameterTypes":["long","long"] }] +}, +{ + "name":"java.nio.channels.FileChannel" +}, +{ + "name":"java.nio.channels.spi.SelectorProvider", + "methods":[{"name":"openServerSocketChannel","parameterTypes":["java.net.ProtocolFamily"] }, {"name":"openSocketChannel","parameterTypes":["java.net.ProtocolFamily"] }] +}, +{ + "name":"java.security.AllPermission" +}, +{ + "name":"java.security.SecurityPermission" +}, +{ + "name":"java.util.Map" +}, +{ + "name":"java.util.PropertyPermission" +}, +{ + "name":"java.util.concurrent.ScheduledThreadPoolExecutor", + "methods":[{"name":"setRemoveOnCancelPolicy","parameterTypes":["boolean"] }] +}, +{ + "name":"java.util.concurrent.atomic.AtomicBoolean", + "fields":[{"name":"value"}] +}, +{ + "name":"java.util.concurrent.atomic.AtomicReference", + "fields":[{"name":"value"}] +}, +{ + "name":"java.util.concurrent.atomic.Striped64", + "fields":[{"name":"base"}, {"name":"cellsBusy"}] +}, +{ + "name":"java.util.concurrent.atomic.Striped64$Cell", + "fields":[{"name":"value"}] +}, +{ + "name":"javax.smartcardio.CardPermission" +}, +{ + "name":"jdk.internal.misc.Unsafe", + "methods":[{"name":"getUnsafe","parameterTypes":[] }] +}, +{ + "name":"kotlin.Array" +}, +{ + "name":"kotlin.Metadata", + "queryAllDeclaredMethods":true, + "methods":[{"name":"bv","parameterTypes":[] }, {"name":"d1","parameterTypes":[] }, {"name":"d2","parameterTypes":[] }, {"name":"k","parameterTypes":[] }, {"name":"mv","parameterTypes":[] }, {"name":"pn","parameterTypes":[] }, {"name":"xi","parameterTypes":[] }, {"name":"xs","parameterTypes":[] }] +}, +{ + "name":"kotlin.SafePublicationLazyImpl", + "fields":[{"name":"_value"}] +}, +{ + "name":"kotlin.String" +}, +{ + "name":"kotlin.Unit" +}, +{ + "name":"kotlin.collections.Map" +}, +{ + "name":"kotlin.jvm.internal.DefaultConstructorMarker" +}, +{ + "name":"kotlin.reflect.jvm.internal.ReflectionFactoryImpl", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"kotlin.reflect.jvm.internal.impl.load.java.ErasedOverridabilityCondition" +}, +{ + "name":"kotlin.reflect.jvm.internal.impl.load.java.FieldOverridabilityCondition" +}, +{ + "name":"kotlin.reflect.jvm.internal.impl.load.java.JavaIncompatibilityRulesOverridabilityCondition" +}, +{ + "name":"kotlin.reflect.jvm.internal.impl.resolve.scopes.DescriptorKindFilter", + "allPublicFields":true +}, +{ + "name":"kotlinx.coroutines.CancellableContinuationImpl", + "fields":[{"name":"_decisionAndIndex$volatile"}, {"name":"_parentHandle$volatile"}, {"name":"_state$volatile"}] +}, +{ + "name":"kotlinx.coroutines.CompletedExceptionally", + "fields":[{"name":"_handled$volatile"}] +}, +{ + "name":"kotlinx.coroutines.EventLoopImplBase", + "fields":[{"name":"_delayed$volatile"}, {"name":"_isCompleted$volatile"}, {"name":"_queue$volatile"}] +}, +{ + "name":"kotlinx.coroutines.JobSupport", + "fields":[{"name":"_parentHandle$volatile"}, {"name":"_state$volatile"}] +}, +{ + "name":"kotlinx.coroutines.JobSupport$Finishing", + "fields":[{"name":"_exceptionsHolder$volatile"}, {"name":"_isCompleting$volatile"}, {"name":"_rootCause$volatile"}] +}, +{ + "name":"kotlinx.coroutines.channels.BufferedChannel", + "fields":[{"name":"_closeCause$volatile"}, {"name":"bufferEnd$volatile"}, {"name":"bufferEndSegment$volatile"}, {"name":"closeHandler$volatile"}, {"name":"completedExpandBuffersAndPauseFlag$volatile"}, {"name":"receiveSegment$volatile"}, {"name":"receivers$volatile"}, {"name":"sendSegment$volatile"}, {"name":"sendersAndCloseStatus$volatile"}] +}, +{ + "name":"kotlinx.coroutines.internal.AtomicOp", + "fields":[{"name":"_consensus$volatile"}] +}, +{ + "name":"kotlinx.coroutines.internal.ConcurrentLinkedListNode", + "fields":[{"name":"_next$volatile"}, {"name":"_prev$volatile"}] +}, +{ + "name":"kotlinx.coroutines.internal.DispatchedContinuation", + "fields":[{"name":"_reusableCancellableContinuation$volatile"}] +}, +{ + "name":"kotlinx.coroutines.internal.LimitedDispatcher", + "fields":[{"name":"runningWorkers$volatile"}] +}, +{ + "name":"kotlinx.coroutines.internal.LockFreeLinkedListNode", + "fields":[{"name":"_next$volatile"}, {"name":"_prev$volatile"}, {"name":"_removedRef$volatile"}] +}, +{ + "name":"kotlinx.coroutines.internal.LockFreeTaskQueue", + "fields":[{"name":"_cur$volatile"}] +}, +{ + "name":"kotlinx.coroutines.internal.LockFreeTaskQueueCore", + "fields":[{"name":"_next$volatile"}, {"name":"_state$volatile"}] +}, +{ + "name":"kotlinx.coroutines.internal.Segment", + "fields":[{"name":"cleanedAndPointers$volatile"}] +}, +{ + "name":"kotlinx.coroutines.scheduling.CoroutineScheduler", + "fields":[{"name":"_isTerminated$volatile"}, {"name":"controlState$volatile"}, {"name":"parkedWorkersStack$volatile"}] +}, +{ + "name":"kotlinx.coroutines.scheduling.CoroutineScheduler$Worker", + "fields":[{"name":"workerCtl$volatile"}] +}, +{ + "name":"kotlinx.coroutines.scheduling.WorkQueue", + "fields":[{"name":"blockingTasksInBuffer$volatile"}, {"name":"consumerIndex$volatile"}, {"name":"lastScheduledTask$volatile"}, {"name":"producerIndex$volatile"}] +}, +{ + "name":"sun.misc.Unsafe", + "fields":[{"name":"theUnsafe"}], + "methods":[{"name":"addressSize","parameterTypes":[] }, {"name":"allocateMemory","parameterTypes":["long"] }, {"name":"arrayBaseOffset","parameterTypes":["java.lang.Class"] }, {"name":"arrayIndexScale","parameterTypes":["java.lang.Class"] }, {"name":"copyMemory","parameterTypes":["java.lang.Object","long","java.lang.Object","long","long"] }, {"name":"freeMemory","parameterTypes":["long"] }, {"name":"getAndAddLong","parameterTypes":["java.lang.Object","long","long"] }, {"name":"getAndSetObject","parameterTypes":["java.lang.Object","long","java.lang.Object"] }, {"name":"getBoolean","parameterTypes":["java.lang.Object","long"] }, {"name":"getByte","parameterTypes":["long"] }, {"name":"getByte","parameterTypes":["java.lang.Object","long"] }, {"name":"getInt","parameterTypes":["long"] }, {"name":"getInt","parameterTypes":["java.lang.Object","long"] }, {"name":"getLong","parameterTypes":["long"] }, {"name":"getLong","parameterTypes":["java.lang.Object","long"] }, {"name":"invokeCleaner","parameterTypes":["java.nio.ByteBuffer"] }, {"name":"objectFieldOffset","parameterTypes":["java.lang.reflect.Field"] }, {"name":"putByte","parameterTypes":["long","byte"] }, {"name":"putByte","parameterTypes":["java.lang.Object","long","byte"] }, {"name":"putInt","parameterTypes":["long","int"] }, {"name":"putInt","parameterTypes":["java.lang.Object","long","int"] }, {"name":"putLong","parameterTypes":["long","long"] }, {"name":"putLong","parameterTypes":["java.lang.Object","long","long"] }, {"name":"reallocateMemory","parameterTypes":["long","long"] }, {"name":"setMemory","parameterTypes":["long","long","byte"] }, {"name":"setMemory","parameterTypes":["java.lang.Object","long","long","byte"] }, {"name":"staticFieldBase","parameterTypes":["java.lang.reflect.Field"] }, {"name":"staticFieldOffset","parameterTypes":["java.lang.reflect.Field"] }, {"name":"storeFence","parameterTypes":[] }] +}, +{ + "name":"sun.misc.VM" +}, +{ + "name":"sun.nio.ch.SelectorImpl", + "fields":[{"name":"publicSelectedKeys"}, {"name":"selectedKeys"}] +} +] \ No newline at end of file diff --git a/native-image-server-with-yaml-config/src/main/resources/META-INF/native-image/resource-config.json b/native-image-server-with-yaml-config/src/main/resources/META-INF/native-image/resource-config.json new file mode 100644 index 00000000..a0b0a117 --- /dev/null +++ b/native-image-server-with-yaml-config/src/main/resources/META-INF/native-image/resource-config.json @@ -0,0 +1,52 @@ +{ + "resources":{ + "includes":[{ + "pattern":"\\QMETA-INF/native/libnetty_transport_native_kqueue.dylib\\E" + }, { + "pattern":"\\QMETA-INF/native/libnetty_transport_native_kqueue.jnilib\\E" + }, { + "pattern":"\\QMETA-INF/native/libnetty_transport_native_kqueue_aarch_64.dylib\\E" + }, { + "pattern":"\\QMETA-INF/native/libnetty_transport_native_kqueue_aarch_64.jnilib\\E" + }, { + "pattern":"\\QMETA-INF/services/ch.qos.logback.classic.spi.Configurator\\E" + }, { + "pattern":"\\QMETA-INF/services/io.ktor.serialization.kotlinx.KotlinxSerializationExtensionProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/io.ktor.server.config.ConfigLoader\\E" + }, { + "pattern":"\\QMETA-INF/services/java.lang.System$LoggerFinder\\E" + }, { + "pattern":"\\QMETA-INF/services/java.nio.channels.spi.SelectorProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/java.time.zone.ZoneRulesProvider\\E" + }, { + "pattern":"\\QMETA-INF/services/javax.xml.parsers.SAXParserFactory\\E" + }, { + "pattern":"\\QMETA-INF/services/kotlin.reflect.jvm.internal.impl.resolve.ExternalOverridabilityCondition\\E" + }, { + "pattern":"\\QMETA-INF/services/kotlin.reflect.jvm.internal.impl.util.ModuleVisibilityHelper\\E" + }, { + "pattern":"\\QMETA-INF/services/org.slf4j.spi.SLF4JServiceProvider\\E" + }, { + "pattern":"\\Qapplication.yaml\\E" + }, { + "pattern":"\\Qkotlin/collections/collections.kotlin_builtins\\E" + }, { + "pattern":"\\Qkotlin/kotlin.kotlin_builtins\\E" + }, { + "pattern":"\\Qlogback-test.scmo\\E" + }, { + "pattern":"\\Qlogback-test.xml\\E" + }, { + "pattern":"\\Qlogback.scmo\\E" + }, { + "pattern":"\\Qlogback.xml\\E" + }, { + "pattern":"java.xml:\\Qjdk/xml/internal/jdkcatalog/JDKCatalog.xml\\E" + }]}, + "bundles":[{ + "name":"sun.util.resources.cldr.CalendarData", + "locales":["und"] + }] +} \ No newline at end of file diff --git a/native-image-server-with-yaml-config/src/main/resources/META-INF/native-image/serialization-config.json b/native-image-server-with-yaml-config/src/main/resources/META-INF/native-image/serialization-config.json new file mode 100644 index 00000000..d0304f2a --- /dev/null +++ b/native-image-server-with-yaml-config/src/main/resources/META-INF/native-image/serialization-config.json @@ -0,0 +1,8 @@ +{ + "types":[ + ], + "lambdaCapturingTypes":[ + ], + "proxies":[ + ] +} \ No newline at end of file diff --git a/native-image-server-with-yaml-config/src/main/resources/application.yaml b/native-image-server-with-yaml-config/src/main/resources/application.yaml new file mode 100644 index 00000000..5f42ed4c --- /dev/null +++ b/native-image-server-with-yaml-config/src/main/resources/application.yaml @@ -0,0 +1,8 @@ +ktor: + application: + modules: + - example.com.ApplicationKt.module + deployment: + port: 8080 + shutdown: + url: "/shutdown" diff --git a/native-image-server-with-yaml-config/src/main/resources/logback.xml b/native-image-server-with-yaml-config/src/main/resources/logback.xml new file mode 100644 index 00000000..3e11d781 --- /dev/null +++ b/native-image-server-with-yaml-config/src/main/resources/logback.xml @@ -0,0 +1,12 @@ + + + + %d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + \ No newline at end of file diff --git a/native-image-server-with-yaml-config/src/test/kotlin/example/com/ApplicationTest.kt b/native-image-server-with-yaml-config/src/test/kotlin/example/com/ApplicationTest.kt new file mode 100644 index 00000000..0f8ca40f --- /dev/null +++ b/native-image-server-with-yaml-config/src/test/kotlin/example/com/ApplicationTest.kt @@ -0,0 +1,21 @@ +package example.com + +import example.com.plugins.* +import io.ktor.client.request.* +import io.ktor.client.statement.* +import io.ktor.http.* +import io.ktor.server.testing.* +import kotlin.test.* + +class ApplicationTest { + @Test + fun testRoot() = testApplication { + application { + configureRouting() + } + client.get("/").apply { + assertEquals(HttpStatusCode.OK, status) + assertEquals("Hello World!", bodyAsText()) + } + } +}