diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5b5d73b..7951c7a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -24,14 +24,16 @@ jobs: java-version: 11 - name: Cache - uses: actions/cache@v2.0.0 + uses: actions/cache@v2 with: # Cache gradle directories path: | ~/.gradle/caches ~/.gradle/wrapper # Key for restoring and saving the cache - key: ${{ runner.os }}-gradle + key: ${{ runner.os }}-gradle-${{ hashFiles("**/*.gradle.kts", "gradle.properties" }} + restore-keys: | + ${{ runner.os }}-gradle- # Compile the code - name: Compile code diff --git a/.github/workflows/publish_snapshots.yml b/.github/workflows/publish_snapshots.yml index 99bdca2..8f490ba 100644 --- a/.github/workflows/publish_snapshots.yml +++ b/.github/workflows/publish_snapshots.yml @@ -19,21 +19,23 @@ jobs: - name: Has SNAPSHOT version id: is-snapshot - run: grep "version =\\? \\?'.*-SNAPSHOT'" build.gradle + run: grep 'version = ".*-SNAPSHOT"' build.gradle.kts - uses: actions/setup-java@v1 with: java-version: 11 - name: Cache - uses: actions/cache@v2.0.0 + uses: actions/cache@v2 with: # Cache gradle directories path: | ~/.gradle/caches ~/.gradle/wrapper # Key for restoring and saving the cache - key: ${{ runner.os }}-gradle + key: ${{ runner.os }}-gradle-${{ hashFiles("**/*.gradle.kts", "gradle.properties" }} + restore-keys: | + ${{ runner.os }}-gradle- - name: Install gpg secret key run: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 00292d2..29ee41c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -19,14 +19,16 @@ jobs: java-version: 11 - name: Cache - uses: actions/cache@v2.0.0 + uses: actions/cache@v2 with: - # A list of files, directories, and wildcard patterns to cache and restore - path: | - ~/.gradle/caches - ~/.gradle/wrapper - # An explicit key for restoring and saving the cache - key: ${{ runner.os }}-gradle + # Cache gradle directories + path: | + ~/.gradle/caches + ~/.gradle/wrapper + # Key for restoring and saving the cache + key: ${{ runner.os }}-gradle-${{ hashFiles("**/*.gradle.kts", "gradle.properties" }} + restore-keys: | + ${{ runner.os }}-gradle- # Compile code - name: Compile code diff --git a/README.md b/README.md index d0ce2ed..bb990f3 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,11 @@ Library to facilitate using with a Jersey-based REST API. This includes OAuth 2. Add this library to your project using the following Gradle configuration: ```gradle repositories { - maven { url "https://dl.bintray.com/radar-base/org.radarbase" } + mavenCentral() } dependencies { - api("org.radarbase:radar-jersey:0.5.0") + api("org.radarbase:radar-jersey:0.6.1") } ``` @@ -110,3 +110,40 @@ fun main(args: Array) { This package adds some error handling. Specifically, `org.radarbase.jersey.exception.HttpApplicationException` and its subclasses can be used and extended to serve detailed error messages with customized logging and HTML templating. They can be thrown from any resource. To serve custom HTML error messages for error codes 400 to 599, add a Mustache template to the classpath in directory `org/radarbase/jersey/exception/mapper/.html`. You can use special cases `4xx.html` and `5xx.html` as a catch-all template. The templates can use variables `status` for the HTTP status code, `code` for short-hand code for the specific error, and an optional `detailedMessage` for a human-readable message. + +## Logging + +To enable logging with radar-jersey, please set the following configurations. For new projects, the default should be Log4j 2. A configuration file is included in the classpath. First include the following dependencies: + +```kotlin +dependencies { + // To enable logging either use log4j + val log4j2Version: String by project + runtimeOnly("org.apache.logging.log4j:log4j-slf4j-impl:$log4j2Version") + runtimeOnly("org.apache.logging.log4j:log4j-api:$log4j2Version") + runtimeOnly("org.apache.logging.log4j:log4j-jul:$log4j2Version") + +} +``` + +Then before any other command is made, set: +```kotlin +// Initialize logging with log4j2 +System.setProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager") +``` +Execute this statement before ANY logging or logging initialization code has been called, for example in the `init` of a companion object of the main class. Alternatively, set it as a Java system property in the command line, i.e. `-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager`. + +If Logback is used instead, import the following dependencies to gradle: + +```kotlin +dependencies { + runtimeOnly("ch.qos.logback:logback-classic:1.2.3") + implementation("org.slf4j:jul-to-slf4j:1.7.30") +} +``` + +Then before any logging code has been called, set: +```kotlin +SLF4JBridgeHandler.removeHandlersForRootLogger() +SLF4JBridgeHandler.install() +``` diff --git a/build.gradle.kts b/build.gradle.kts index 38b75a3..1bfa32d 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -7,16 +7,32 @@ plugins { `maven-publish` signing id("org.jetbrains.dokka") apply false - id("com.github.ben-manes.versions") version "0.36.0" apply false - id("io.github.gradle-nexus.publish-plugin") version "1.0.0" + id("com.github.ben-manes.versions") version "0.38.0" + id("io.github.gradle-nexus.publish-plugin") version "1.1.0" +} + +fun isNonStable(version: String): Boolean { + val stableKeyword = listOf("RELEASE", "FINAL", "GA").any { version.toUpperCase().contains(it) } + val regex = "^[0-9,.v-]+(-r)?$".toRegex() + val isStable = stableKeyword || regex.matches(version) + return isStable.not() } allprojects { group = "org.radarbase" - version = "0.6.0" + version = "0.6.1" + + afterEvaluate { + tasks.withType { + rejectVersionIf { + isNonStable(candidate.version) + } + } + } } subprojects { + apply(plugin = "kotlin") apply(plugin = "maven-publish") apply(plugin = "signing") apply(plugin = "com.github.ben-manes.versions") @@ -34,19 +50,6 @@ subprojects { set("githubIssueUrl", githubIssueUrl) } - fun isNonStable(version: String): Boolean { - val stableKeyword = listOf("RELEASE", "FINAL", "GA").any { version.toUpperCase().contains(it) } - val regex = "^[0-9,.v-]+(-r)?$".toRegex() - val isStable = stableKeyword || regex.matches(version) - return isStable.not() - } - - tasks.named("dependencyUpdates").configure { - rejectVersionIf { - isNonStable(candidate.version) - } - } - repositories { mavenCentral() // Temporary until Dokka is fully published on maven central. @@ -57,6 +60,12 @@ subprojects { dependencies { val dokkaVersion: String by project configurations["dokkaHtmlPlugin"]("org.jetbrains.dokka:kotlin-as-java-plugin:$dokkaVersion") + + val log4j2Version: String by project + val testRuntimeOnly by configurations + testRuntimeOnly("org.apache.logging.log4j:log4j-slf4j-impl:$log4j2Version") + testRuntimeOnly("org.apache.logging.log4j:log4j-api:$log4j2Version") + testRuntimeOnly("org.apache.logging.log4j:log4j-jul:$log4j2Version") } val sourcesJar by tasks.registering(Jar::class) { @@ -89,6 +98,7 @@ subprojects { exceptionFormat = FULL } useJUnitPlatform() + systemProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager") } tasks.withType { @@ -191,5 +201,5 @@ nexusPublishing { } tasks.wrapper { - gradleVersion = "7.0" + gradleVersion = "7.0.2" } diff --git a/gradle.properties b/gradle.properties index c015630..1ee9432 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,28 +3,29 @@ org.gradle.jvmargs=-Xmx2000m org.gradle.vfs.watch=true kotlin.code.style=official -kotlinVersion=1.4.32 -dokkaVersion=1.4.30 +kotlinVersion=1.5.0 +dokkaVersion=1.4.32 -jerseyVersion=3.0.1 +jerseyVersion=3.0.2 grizzlyVersion=3.0.0 okhttpVersion=4.9.1 -junitVersion=5.7.1 +junitVersion=5.7.2 hk2Version=2.6.1 -managementPortalVersion=0.7.0 -javaJwtVersion=3.12.0 +managementPortalVersion=0.7.1 +javaJwtVersion=3.16.0 jakartaWsRsVersion=3.0.0 jakartaAnnotationVersion=2.0.0 jacksonVersion=2.12.3 slf4jVersion=1.7.30 -jakartaXmlBindVersion=3.0.0 -jakartaJaxbCoreVersion=3.0.0 -jakartaJaxbRuntimeVersion=3.0.0 +log4j2Version=2.14.1 +jakartaXmlBindVersion=3.0.1 +jakartaJaxbCoreVersion=3.0.1 +jakartaJaxbRuntimeVersion=3.0.1 jakartaActivation=2.0.1 -swaggerVersion=2.1.7 +swaggerVersion=2.1.9 -hibernateVersion=5.4.30.Final -liquibaseVersion=4.3.3 -postgresVersion=42.2.19 +hibernateVersion=5.4.31.Final +liquibaseVersion=4.3.5 +postgresVersion=42.2.20 h2Version=1.4.200 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f371643..0f80bbf 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/radar-jersey-hibernate/build.gradle.kts b/radar-jersey-hibernate/build.gradle.kts index bda23c7..eed2422 100644 --- a/radar-jersey-hibernate/build.gradle.kts +++ b/radar-jersey-hibernate/build.gradle.kts @@ -36,6 +36,4 @@ dependencies { testImplementation("org.hamcrest:hamcrest-all:1.3") val okhttpVersion: String by project testImplementation("com.squareup.okhttp3:okhttp:$okhttpVersion") - - testRuntimeOnly("ch.qos.logback:logback-classic:1.2.3") } diff --git a/radar-jersey-hibernate/src/main/kotlin/org/radarbase/jersey/hibernate/DatabaseInitialization.kt b/radar-jersey-hibernate/src/main/kotlin/org/radarbase/jersey/hibernate/DatabaseInitialization.kt index 020b737..67feb1c 100644 --- a/radar-jersey-hibernate/src/main/kotlin/org/radarbase/jersey/hibernate/DatabaseInitialization.kt +++ b/radar-jersey-hibernate/src/main/kotlin/org/radarbase/jersey/hibernate/DatabaseInitialization.kt @@ -20,20 +20,20 @@ import jakarta.ws.rs.ext.Provider @Provider class DatabaseInitialization( - @Context private val entityManagerFactory: jakarta.inject.Provider, - @Context private val dbConfig: DatabaseConfig, + @Context private val entityManagerFactory: jakarta.inject.Provider, + @Context private val dbConfig: DatabaseConfig, ) : ApplicationEventListener { + override fun onEvent(event: ApplicationEvent) { - logger.info("Application state: {}", event.type) if (event.type != ApplicationEvent.Type.INITIALIZATION_APP_FINISHED) return try { entityManagerFactory.get().useEntityManager { - // make first connection - it.connection().use { connection -> - if (dbConfig.liquibase.enable) { - initializeLiquibase(connection) - } + // make first connection + it.connection().use { connection -> + if (dbConfig.liquibase.enable) { + initializeLiquibase(connection) } + } } } catch (ex: Throwable) { throw IllegalStateException("Cannot initialize database.", ex) @@ -43,11 +43,13 @@ class DatabaseInitialization( private fun initializeLiquibase(connection: Connection) { logger.info("Initializing Liquibase") val database = DatabaseFactory.getInstance() - .findCorrectDatabaseImplementation( - JdbcConnection(connection)) - Liquibase(dbConfig.liquibase.changelogs, ClassLoaderResourceAccessor(), database).use { - it.update(null as Contexts?) - } + .findCorrectDatabaseImplementation(JdbcConnection(connection)) + + Liquibase( + dbConfig.liquibase.changelogs, + ClassLoaderResourceAccessor(), + database, + ).use { it.update(null as Contexts?) } } override fun onRequest(requestEvent: RequestEvent?): RequestEventListener? = null diff --git a/radar-jersey-hibernate/src/test/kotlin/org/radarbase/jersey/hibernate/HibernateTest.kt b/radar-jersey-hibernate/src/test/kotlin/org/radarbase/jersey/hibernate/HibernateTest.kt index 95571b6..34aa5a6 100644 --- a/radar-jersey-hibernate/src/test/kotlin/org/radarbase/jersey/hibernate/HibernateTest.kt +++ b/radar-jersey-hibernate/src/test/kotlin/org/radarbase/jersey/hibernate/HibernateTest.kt @@ -79,7 +79,6 @@ internal class HibernateTest { override fun writeTo(sink: BufferedSink) { sink.writeUtf8("{\"name\": \"a\"}") } - }) .url("http://localhost:9091/projects") .build()).execute().use { response -> diff --git a/radar-jersey/build.gradle.kts b/radar-jersey/build.gradle.kts index 15e7b3b..77aa49f 100644 --- a/radar-jersey/build.gradle.kts +++ b/radar-jersey/build.gradle.kts @@ -68,8 +68,6 @@ dependencies { val junitVersion: String by project testImplementation("org.junit.jupiter:junit-jupiter:$junitVersion") testImplementation("org.hamcrest:hamcrest-all:1.3") - - testRuntimeOnly("ch.qos.logback:logback-classic:1.2.3") } tasks.processResources { diff --git a/radar-jersey/src/main/kotlin/org/radarbase/jersey/auth/Auth.kt b/radar-jersey/src/main/kotlin/org/radarbase/jersey/auth/Auth.kt index 875fa0a..a8a6229 100644 --- a/radar-jersey/src/main/kotlin/org/radarbase/jersey/auth/Auth.kt +++ b/radar-jersey/src/main/kotlin/org/radarbase/jersey/auth/Auth.kt @@ -146,6 +146,7 @@ interface Auth { get() = startsWith("logPermission") || startsWith("checkPermission") || startsWith("invoke") + || startsWith("internal") private val Class<*>.isAuthClass: Boolean get() = isInstance(Auth::class.java) diff --git a/radar-jersey/src/main/kotlin/org/radarbase/jersey/auth/filter/AuthenticationFilter.kt b/radar-jersey/src/main/kotlin/org/radarbase/jersey/auth/filter/AuthenticationFilter.kt index 78455d3..6372eb9 100644 --- a/radar-jersey/src/main/kotlin/org/radarbase/jersey/auth/filter/AuthenticationFilter.kt +++ b/radar-jersey/src/main/kotlin/org/radarbase/jersey/auth/filter/AuthenticationFilter.kt @@ -29,7 +29,7 @@ import jakarta.ws.rs.ext.Provider @Priority(Priorities.AUTHENTICATION) @Singleton class AuthenticationFilter( - @Context private val validator: AuthValidator + @Context private val validator: AuthValidator, ) : ContainerRequestFilter { override fun filter(requestContext: ContainerRequestContext) { diff --git a/radar-jersey/src/main/kotlin/org/radarbase/jersey/config/ConfigLoader.kt b/radar-jersey/src/main/kotlin/org/radarbase/jersey/config/ConfigLoader.kt index 5e98eb1..5f1835d 100644 --- a/radar-jersey/src/main/kotlin/org/radarbase/jersey/config/ConfigLoader.kt +++ b/radar-jersey/src/main/kotlin/org/radarbase/jersey/config/ConfigLoader.kt @@ -4,7 +4,6 @@ import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.dataformat.yaml.YAMLFactory import com.fasterxml.jackson.module.kotlin.KotlinModule import io.swagger.v3.oas.models.OpenAPI -import io.swagger.v3.oas.models.info.Info import org.glassfish.jersey.internal.inject.AbstractBinder import org.glassfish.jersey.server.ResourceConfig import org.radarbase.jersey.auth.AuthConfig @@ -118,6 +117,7 @@ object ConfigLoader { val health = HealthResourceEnhancer() val httpException = HttpExceptionResourceEnhancer() val generalException = GeneralExceptionResourceEnhancer() + val utility = UtilityResourceEnhancer() fun swagger(openApi: OpenAPI, resourcePackages: Set? = null) = SwaggerResourceEnhancer(openApi, resourcePackages) } diff --git a/radar-jersey/src/main/kotlin/org/radarbase/jersey/config/DisabledAuthorizationResourceEnhancer.kt b/radar-jersey/src/main/kotlin/org/radarbase/jersey/config/DisabledAuthorizationResourceEnhancer.kt index eeecd86..d687156 100644 --- a/radar-jersey/src/main/kotlin/org/radarbase/jersey/config/DisabledAuthorizationResourceEnhancer.kt +++ b/radar-jersey/src/main/kotlin/org/radarbase/jersey/config/DisabledAuthorizationResourceEnhancer.kt @@ -21,7 +21,7 @@ import jakarta.inject.Singleton class DisabledAuthorizationResourceEnhancer : JerseyResourceEnhancer { override fun AbstractBinder.enhance() { bind(DisabledAuthValidator::class.java) - .to(AuthValidator::class.java) - .`in`(Singleton::class.java) + .to(AuthValidator::class.java) + .`in`(Singleton::class.java) } } diff --git a/radar-jersey/src/main/kotlin/org/radarbase/jersey/config/EcdsaResourceEnhancer.kt b/radar-jersey/src/main/kotlin/org/radarbase/jersey/config/EcdsaResourceEnhancer.kt index 1e5d002..4d6616b 100644 --- a/radar-jersey/src/main/kotlin/org/radarbase/jersey/config/EcdsaResourceEnhancer.kt +++ b/radar-jersey/src/main/kotlin/org/radarbase/jersey/config/EcdsaResourceEnhancer.kt @@ -24,7 +24,7 @@ import jakarta.inject.Singleton class EcdsaResourceEnhancer : JerseyResourceEnhancer { override fun AbstractBinder.enhance() { bind(EcdsaJwtTokenValidator::class.java) - .to(AuthValidator::class.java) - .`in`(Singleton::class.java) + .to(AuthValidator::class.java) + .`in`(Singleton::class.java) } } diff --git a/radar-jersey/src/main/kotlin/org/radarbase/jersey/config/GeneralExceptionResourceEnhancer.kt b/radar-jersey/src/main/kotlin/org/radarbase/jersey/config/GeneralExceptionResourceEnhancer.kt index 2226a4c..c47946b 100644 --- a/radar-jersey/src/main/kotlin/org/radarbase/jersey/config/GeneralExceptionResourceEnhancer.kt +++ b/radar-jersey/src/main/kotlin/org/radarbase/jersey/config/GeneralExceptionResourceEnhancer.kt @@ -6,6 +6,7 @@ import org.radarbase.jersey.exception.mapper.WebApplicationExceptionMapper /** Add WebApplicationException and any exception handling. */ class GeneralExceptionResourceEnhancer: JerseyResourceEnhancer { override val classes: Array> = arrayOf( - UnhandledExceptionMapper::class.java, - WebApplicationExceptionMapper::class.java) + UnhandledExceptionMapper::class.java, + WebApplicationExceptionMapper::class.java, + ) } diff --git a/radar-jersey/src/main/kotlin/org/radarbase/jersey/config/HealthResourceEnhancer.kt b/radar-jersey/src/main/kotlin/org/radarbase/jersey/config/HealthResourceEnhancer.kt index fea2990..0bc5535 100644 --- a/radar-jersey/src/main/kotlin/org/radarbase/jersey/config/HealthResourceEnhancer.kt +++ b/radar-jersey/src/main/kotlin/org/radarbase/jersey/config/HealthResourceEnhancer.kt @@ -11,7 +11,7 @@ class HealthResourceEnhancer: JerseyResourceEnhancer { override fun AbstractBinder.enhance() { bind(ImmediateHealthService::class.java) - .to(HealthService::class.java) - .`in`(Singleton::class.java) + .to(HealthService::class.java) + .`in`(Singleton::class.java) } } diff --git a/radar-jersey/src/main/kotlin/org/radarbase/jersey/config/HttpExceptionResourceEnhancer.kt b/radar-jersey/src/main/kotlin/org/radarbase/jersey/config/HttpExceptionResourceEnhancer.kt index 457a634..5215bf0 100644 --- a/radar-jersey/src/main/kotlin/org/radarbase/jersey/config/HttpExceptionResourceEnhancer.kt +++ b/radar-jersey/src/main/kotlin/org/radarbase/jersey/config/HttpExceptionResourceEnhancer.kt @@ -12,18 +12,18 @@ class HttpExceptionResourceEnhancer: JerseyResourceEnhancer { override fun AbstractBinder.enhance() { bind(HtmlTemplateExceptionRenderer::class.java) - .to(ExceptionRenderer::class.java) - .named("text/html") - .`in`(PerThread::class.java) + .to(ExceptionRenderer::class.java) + .named("text/html") + .`in`(PerThread::class.java) bind(DefaultJsonExceptionRenderer::class.java) - .to(ExceptionRenderer::class.java) - .named("application/json") - .`in`(Singleton::class.java) + .to(ExceptionRenderer::class.java) + .named("application/json") + .`in`(Singleton::class.java) bind(DefaultTextExceptionRenderer::class.java) - .to(ExceptionRenderer::class.java) - .named("text/plain") - .`in`(Singleton::class.java) + .to(ExceptionRenderer::class.java) + .named("text/plain") + .`in`(Singleton::class.java) } } diff --git a/radar-jersey/src/main/kotlin/org/radarbase/jersey/config/RadarJerseyResourceEnhancer.kt b/radar-jersey/src/main/kotlin/org/radarbase/jersey/config/RadarJerseyResourceEnhancer.kt index 292bdec..ea4a61e 100644 --- a/radar-jersey/src/main/kotlin/org/radarbase/jersey/config/RadarJerseyResourceEnhancer.kt +++ b/radar-jersey/src/main/kotlin/org/radarbase/jersey/config/RadarJerseyResourceEnhancer.kt @@ -9,13 +9,7 @@ package org.radarbase.jersey.config -import com.fasterxml.jackson.annotation.JsonInclude -import com.fasterxml.jackson.databind.DeserializationFeature -import com.fasterxml.jackson.databind.ObjectMapper -import com.fasterxml.jackson.databind.SerializationFeature -import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule -import com.fasterxml.jackson.module.kotlin.KotlinModule -import okhttp3.OkHttpClient +import jakarta.inject.Singleton import org.glassfish.jersey.internal.inject.AbstractBinder import org.glassfish.jersey.process.internal.RequestScoped import org.glassfish.jersey.server.ResourceConfig @@ -24,52 +18,41 @@ import org.radarbase.jersey.auth.AuthConfig import org.radarbase.jersey.auth.filter.AuthenticationFilter import org.radarbase.jersey.auth.filter.AuthorizationFeature import org.radarbase.jersey.auth.jwt.AuthFactory -import java.util.concurrent.TimeUnit -import jakarta.ws.rs.ext.ContextResolver /** * Add RADAR auth to a Jersey project. This requires a {@link ProjectService} implementation to be * added to the Binder first. */ class RadarJerseyResourceEnhancer( - private val config: AuthConfig + private val config: AuthConfig, ): JerseyResourceEnhancer { - var mapper: ObjectMapper = ObjectMapper() - .setSerializationInclusion(JsonInclude.Include.NON_NULL) - .registerModule(JavaTimeModule()) - .registerModule(KotlinModule()) - .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false) - .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - - var client: OkHttpClient = OkHttpClient().newBuilder() - .connectTimeout(10, TimeUnit.SECONDS) - .writeTimeout(10, TimeUnit.SECONDS) - .readTimeout(30, TimeUnit.SECONDS) - .build() + /** + * Utilities. Set to `null` to avoid injection. Modify utility mapper or client to inject + * a different mapper or client. + */ + var utilityResourceEnhancer: UtilityResourceEnhancer? = UtilityResourceEnhancer() override val classes = arrayOf( - AuthenticationFilter::class.java, - AuthorizationFeature::class.java) + AuthenticationFilter::class.java, + AuthorizationFeature::class.java, + ) override fun ResourceConfig.enhance() { - register(ContextResolver { mapper }) + utilityResourceEnhancer?.enhanceResources(this) } override fun AbstractBinder.enhance() { - bind(config.withEnv()) - .to(AuthConfig::class.java) - - bind(client) - .to(OkHttpClient::class.java) - - bind(mapper) - .to(ObjectMapper::class.java) + bindFactory { config.withEnv() } + .to(AuthConfig::class.java) + .`in`(Singleton::class.java) // Bind factories. bindFactory(AuthFactory::class.java) - .proxy(true) - .proxyForSameScope(true) - .to(Auth::class.java) - .`in`(RequestScoped::class.java) + .proxy(true) + .proxyForSameScope(true) + .to(Auth::class.java) + .`in`(RequestScoped::class.java) + + utilityResourceEnhancer?.enhanceBinder(this) } } diff --git a/radar-jersey/src/main/kotlin/org/radarbase/jersey/config/UtilityResourceEnhancer.kt b/radar-jersey/src/main/kotlin/org/radarbase/jersey/config/UtilityResourceEnhancer.kt new file mode 100644 index 0000000..1ca2c99 --- /dev/null +++ b/radar-jersey/src/main/kotlin/org/radarbase/jersey/config/UtilityResourceEnhancer.kt @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2019. The Hyve + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * + * See the file LICENSE in the root of this repository. + */ + +package org.radarbase.jersey.config + +import com.fasterxml.jackson.annotation.JsonInclude +import com.fasterxml.jackson.databind.DeserializationFeature +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.databind.SerializationFeature +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule +import com.fasterxml.jackson.module.kotlin.KotlinModule +import jakarta.inject.Singleton +import jakarta.ws.rs.ext.ContextResolver +import okhttp3.OkHttpClient +import org.glassfish.jersey.internal.inject.AbstractBinder +import org.glassfish.jersey.process.internal.RequestScoped +import org.glassfish.jersey.server.ResourceConfig +import org.radarbase.jersey.auth.Auth +import org.radarbase.jersey.auth.jwt.AuthFactory +import java.util.concurrent.TimeUnit + +/** + * Add utilities such as a reusable ObjectMapper and OkHttpClient to inject. + * + * Do not use this class if [RadarJerseyResourceEnhancer] is already being used. + */ +class UtilityResourceEnhancer: JerseyResourceEnhancer { + var mapper: ObjectMapper = ObjectMapper() + .setSerializationInclusion(JsonInclude.Include.NON_NULL) + .registerModule(JavaTimeModule()) + .registerModule(KotlinModule()) + .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false) + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + + var client: OkHttpClient = OkHttpClient().newBuilder() + .connectTimeout(10, TimeUnit.SECONDS) + .writeTimeout(10, TimeUnit.SECONDS) + .readTimeout(30, TimeUnit.SECONDS) + .build() + + override fun ResourceConfig.enhance() { + register(ContextResolver { mapper }) + } + + override fun AbstractBinder.enhance() { + bindFactory { client } + .to(OkHttpClient::class.java) + .`in`(Singleton::class.java) + + bindFactory { mapper } + .to(ObjectMapper::class.java) + .`in`(Singleton::class.java) + + // Bind factories. + bindFactory(AuthFactory::class.java) + .proxy(true) + .proxyForSameScope(true) + .to(Auth::class.java) + .`in`(RequestScoped::class.java) + } +} diff --git a/radar-jersey/src/main/kotlin/org/radarbase/jersey/doc/swagger/SwaggerResourceEnhancer.kt b/radar-jersey/src/main/kotlin/org/radarbase/jersey/doc/swagger/SwaggerResourceEnhancer.kt index f998008..3b33f94 100644 --- a/radar-jersey/src/main/kotlin/org/radarbase/jersey/doc/swagger/SwaggerResourceEnhancer.kt +++ b/radar-jersey/src/main/kotlin/org/radarbase/jersey/doc/swagger/SwaggerResourceEnhancer.kt @@ -6,7 +6,6 @@ import io.swagger.v3.oas.models.OpenAPI import org.glassfish.jersey.server.ResourceConfig import org.radarbase.jersey.config.JerseyResourceEnhancer - class SwaggerResourceEnhancer( private val openApi: OpenAPI, private val ignoredRoutes: Set? = null, diff --git a/radar-jersey/src/main/resources/log4j2.xml b/radar-jersey/src/main/resources/log4j2.xml new file mode 100644 index 0000000..84e7175 --- /dev/null +++ b/radar-jersey/src/main/resources/log4j2.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/radar-jersey/src/main/resources/logback.xml b/radar-jersey/src/main/resources/logback.xml index 09af2c1..3ae3656 100644 --- a/radar-jersey/src/main/resources/logback.xml +++ b/radar-jersey/src/main/resources/logback.xml @@ -1,4 +1,8 @@ + + true + +