diff --git a/extensions/resteasy-classic/rest-client-config/deployment/pom.xml b/extensions/resteasy-classic/rest-client-config/deployment/pom.xml index 12ec359b90237..22dfdbb1b1356 100644 --- a/extensions/resteasy-classic/rest-client-config/deployment/pom.xml +++ b/extensions/resteasy-classic/rest-client-config/deployment/pom.xml @@ -54,9 +54,6 @@ ${project.version} - - -AlegacyConfigRoot=true - diff --git a/extensions/resteasy-classic/resteasy-multipart/deployment/pom.xml b/extensions/resteasy-classic/resteasy-multipart/deployment/pom.xml index 82213eb9b5838..d20e6b79e3f73 100644 --- a/extensions/resteasy-classic/resteasy-multipart/deployment/pom.xml +++ b/extensions/resteasy-classic/resteasy-multipart/deployment/pom.xml @@ -53,9 +53,6 @@ ${project.version} - - -AlegacyConfigRoot=true - diff --git a/extensions/resteasy-classic/resteasy-server-common/runtime/pom.xml b/extensions/resteasy-classic/resteasy-server-common/runtime/pom.xml index 30cbd77151de2..75257c4be6704 100644 --- a/extensions/resteasy-classic/resteasy-server-common/runtime/pom.xml +++ b/extensions/resteasy-classic/resteasy-server-common/runtime/pom.xml @@ -54,9 +54,6 @@ ${project.version} - - -AlegacyConfigRoot=true - diff --git a/extensions/resteasy-classic/resteasy/deployment/pom.xml b/extensions/resteasy-classic/resteasy/deployment/pom.xml index 8f08934d78201..0dd9e6368ac83 100644 --- a/extensions/resteasy-classic/resteasy/deployment/pom.xml +++ b/extensions/resteasy-classic/resteasy/deployment/pom.xml @@ -107,9 +107,6 @@ ${project.version} - - -AlegacyConfigRoot=true - diff --git a/extensions/resteasy-reactive/rest-client/deployment/pom.xml b/extensions/resteasy-reactive/rest-client/deployment/pom.xml index 276960655b48f..d0a49dc0fc3d9 100644 --- a/extensions/resteasy-reactive/rest-client/deployment/pom.xml +++ b/extensions/resteasy-reactive/rest-client/deployment/pom.xml @@ -128,9 +128,6 @@ ${project.version} - - -AlegacyConfigRoot=true - diff --git a/extensions/resteasy-reactive/rest-csrf/deployment/pom.xml b/extensions/resteasy-reactive/rest-csrf/deployment/pom.xml index 1ce8f6a8c71bc..ac74515d94073 100644 --- a/extensions/resteasy-reactive/rest-csrf/deployment/pom.xml +++ b/extensions/resteasy-reactive/rest-csrf/deployment/pom.xml @@ -65,9 +65,6 @@ ${project.version} - - -AlegacyConfigRoot=true - diff --git a/extensions/resteasy-reactive/rest-csrf/deployment/src/main/java/io/quarkus/csrf/reactive/RestCsrfBuildTimeConfig.java b/extensions/resteasy-reactive/rest-csrf/deployment/src/main/java/io/quarkus/csrf/reactive/RestCsrfBuildTimeConfig.java deleted file mode 100644 index cfa6b43c44eb3..0000000000000 --- a/extensions/resteasy-reactive/rest-csrf/deployment/src/main/java/io/quarkus/csrf/reactive/RestCsrfBuildTimeConfig.java +++ /dev/null @@ -1,16 +0,0 @@ -package io.quarkus.csrf.reactive; - -import io.quarkus.runtime.annotations.ConfigItem; -import io.quarkus.runtime.annotations.ConfigRoot; - -/** - * Build time configuration for CSRF Reactive Filter. - */ -@ConfigRoot -public class RestCsrfBuildTimeConfig { - /** - * If filter is enabled. - */ - @ConfigItem(defaultValue = "true") - public boolean enabled; -} diff --git a/extensions/resteasy-reactive/rest-csrf/deployment/src/main/java/io/quarkus/csrf/reactive/CsrfReactiveAlwaysEnabledProcessor.java b/extensions/resteasy-reactive/rest-csrf/deployment/src/main/java/io/quarkus/csrf/reactive/deployment/CsrfReactiveAlwaysEnabledProcessor.java similarity index 90% rename from extensions/resteasy-reactive/rest-csrf/deployment/src/main/java/io/quarkus/csrf/reactive/CsrfReactiveAlwaysEnabledProcessor.java rename to extensions/resteasy-reactive/rest-csrf/deployment/src/main/java/io/quarkus/csrf/reactive/deployment/CsrfReactiveAlwaysEnabledProcessor.java index 5c70023a51e38..908f3203347e2 100644 --- a/extensions/resteasy-reactive/rest-csrf/deployment/src/main/java/io/quarkus/csrf/reactive/CsrfReactiveAlwaysEnabledProcessor.java +++ b/extensions/resteasy-reactive/rest-csrf/deployment/src/main/java/io/quarkus/csrf/reactive/deployment/CsrfReactiveAlwaysEnabledProcessor.java @@ -1,4 +1,4 @@ -package io.quarkus.csrf.reactive; +package io.quarkus.csrf.reactive.deployment; import io.quarkus.deployment.Feature; import io.quarkus.deployment.annotations.BuildStep; diff --git a/extensions/resteasy-reactive/rest-csrf/deployment/src/main/java/io/quarkus/csrf/reactive/CsrfReactiveBuildStep.java b/extensions/resteasy-reactive/rest-csrf/deployment/src/main/java/io/quarkus/csrf/reactive/deployment/CsrfReactiveBuildStep.java similarity index 95% rename from extensions/resteasy-reactive/rest-csrf/deployment/src/main/java/io/quarkus/csrf/reactive/CsrfReactiveBuildStep.java rename to extensions/resteasy-reactive/rest-csrf/deployment/src/main/java/io/quarkus/csrf/reactive/deployment/CsrfReactiveBuildStep.java index acc0178562f70..3db5f880bfefe 100644 --- a/extensions/resteasy-reactive/rest-csrf/deployment/src/main/java/io/quarkus/csrf/reactive/CsrfReactiveBuildStep.java +++ b/extensions/resteasy-reactive/rest-csrf/deployment/src/main/java/io/quarkus/csrf/reactive/deployment/CsrfReactiveBuildStep.java @@ -1,4 +1,4 @@ -package io.quarkus.csrf.reactive; +package io.quarkus.csrf.reactive.deployment; import java.util.function.BooleanSupplier; @@ -31,7 +31,7 @@ public static class IsEnabled implements BooleanSupplier { RestCsrfBuildTimeConfig config; public boolean getAsBoolean() { - return config.enabled; + return config.enabled(); } } } diff --git a/extensions/resteasy-reactive/rest-csrf/deployment/src/main/java/io/quarkus/csrf/reactive/deployment/RestCsrfBuildTimeConfig.java b/extensions/resteasy-reactive/rest-csrf/deployment/src/main/java/io/quarkus/csrf/reactive/deployment/RestCsrfBuildTimeConfig.java new file mode 100644 index 0000000000000..9a7a1cdde0896 --- /dev/null +++ b/extensions/resteasy-reactive/rest-csrf/deployment/src/main/java/io/quarkus/csrf/reactive/deployment/RestCsrfBuildTimeConfig.java @@ -0,0 +1,18 @@ +package io.quarkus.csrf.reactive.deployment; + +import io.quarkus.runtime.annotations.ConfigRoot; +import io.smallrye.config.ConfigMapping; +import io.smallrye.config.WithDefault; + +/** + * Build time configuration for CSRF Reactive Filter. + */ +@ConfigRoot +@ConfigMapping(prefix = "quarkus.rest-csrf") +public interface RestCsrfBuildTimeConfig { + /** + * If filter is enabled. + */ + @WithDefault("true") + boolean enabled(); +} diff --git a/extensions/resteasy-reactive/rest-csrf/runtime/pom.xml b/extensions/resteasy-reactive/rest-csrf/runtime/pom.xml index ba6223dc9bf34..dc1d3ce25a230 100644 --- a/extensions/resteasy-reactive/rest-csrf/runtime/pom.xml +++ b/extensions/resteasy-reactive/rest-csrf/runtime/pom.xml @@ -55,9 +55,6 @@ ${project.version} - - -AlegacyConfigRoot=true - diff --git a/extensions/resteasy-reactive/rest-csrf/runtime/src/main/java/io/quarkus/csrf/reactive/runtime/CsrfRequestResponseReactiveFilter.java b/extensions/resteasy-reactive/rest-csrf/runtime/src/main/java/io/quarkus/csrf/reactive/runtime/CsrfRequestResponseReactiveFilter.java index 3d5d23615804d..916585380963f 100644 --- a/extensions/resteasy-reactive/rest-csrf/runtime/src/main/java/io/quarkus/csrf/reactive/runtime/CsrfRequestResponseReactiveFilter.java +++ b/extensions/resteasy-reactive/rest-csrf/runtime/src/main/java/io/quarkus/csrf/reactive/runtime/CsrfRequestResponseReactiveFilter.java @@ -70,7 +70,7 @@ public void filter(ResteasyReactiveContainerRequestContext requestContext, Routi try { int cookieTokenSize = Base64.getUrlDecoder().decode(cookieToken).length; // HMAC SHA256 output is 32 bytes long - int expectedCookieTokenSize = config.tokenSignatureKey.isPresent() ? 32 : config.tokenSize; + int expectedCookieTokenSize = config.tokenSignatureKey().isPresent() ? 32 : config.tokenSize(); if (cookieTokenSize != expectedCookieTokenSize) { LOG.debugf("Invalid CSRF token cookie size: expected %d, got %d", expectedCookieTokenSize, cookieTokenSize); @@ -90,12 +90,12 @@ public void filter(ResteasyReactiveContainerRequestContext requestContext, Routi if (cookieToken == null) { generateNewCsrfToken(routing, config); } else { - String csrfTokenHeaderParam = requestContext.getHeaderString(config.tokenHeaderName); + String csrfTokenHeaderParam = requestContext.getHeaderString(config.tokenHeaderName()); if (csrfTokenHeaderParam != null) { LOG.debugf("CSRF token found in the token header"); // Verify the header, make sure the header value, possibly signed, is returned as the next cookie value verifyCsrfToken(requestContext, routing, config, cookieToken, csrfTokenHeaderParam); - } else if (!config.tokenSignatureKey.isEmpty()) { + } else if (!config.tokenSignatureKey().isEmpty()) { // If the signature is required, then we can not use the current cookie value // as the HTML form token key because it represents a signed value of the previous key // and it will lead to the double-signing issue if this value is reused as the key. @@ -109,11 +109,11 @@ public void filter(ResteasyReactiveContainerRequestContext requestContext, Routi } routing.put(NEW_COOKIE_REQUIRED, true); } - } else if (config.verifyToken) { + } else if (config.verifyToken()) { // unsafe HTTP method, token is required // Check the header first - String csrfTokenHeaderParam = requestContext.getHeaderString(config.tokenHeaderName); + String csrfTokenHeaderParam = requestContext.getHeaderString(config.tokenHeaderName()); if (csrfTokenHeaderParam != null) { LOG.debugf("CSRF token found in the token header"); verifyCsrfToken(requestContext, routing, config, cookieToken, csrfTokenHeaderParam); @@ -124,7 +124,7 @@ public void filter(ResteasyReactiveContainerRequestContext requestContext, Routi MediaType mediaType = requestContext.getMediaType(); if (!isMatchingMediaType(mediaType, MediaType.APPLICATION_FORM_URLENCODED_TYPE) && !isMatchingMediaType(mediaType, MediaType.MULTIPART_FORM_DATA_TYPE)) { - if (config.requireFormUrlEncoded) { + if (config.requireFormUrlEncoded()) { LOG.debugf("Request has the wrong media type: %s", mediaType); requestContext.abortWith(badClientRequest()); return; @@ -143,7 +143,7 @@ public void filter(ResteasyReactiveContainerRequestContext requestContext, Routi ResteasyReactiveRequestContext rrContext = (ResteasyReactiveRequestContext) requestContext .getServerRequestContext(); - String csrfTokenFormParam = (String) rrContext.getFormParameter(config.formFieldName, true, false); + String csrfTokenFormParam = (String) rrContext.getFormParameter(config.formFieldName(), true, false); LOG.debugf("CSRF token found in the form parameter"); verifyCsrfToken(requestContext, routing, config, cookieToken, csrfTokenFormParam); @@ -155,7 +155,7 @@ public void filter(ResteasyReactiveContainerRequestContext requestContext, Routi private void generateNewCsrfToken(RoutingContext routing, RestCsrfConfig config) { // Set the CSRF cookie with a randomly generated value - byte[] tokenBytes = new byte[config.tokenSize]; + byte[] tokenBytes = new byte[config.tokenSize()]; secureRandom.nextBytes(tokenBytes); routing.put(CSRF_TOKEN_BYTES_KEY, tokenBytes); routing.put(CSRF_TOKEN_KEY, Base64.getUrlEncoder().withoutPadding().encodeToString(tokenBytes)); @@ -173,8 +173,8 @@ private void verifyCsrfToken(ResteasyReactiveContainerRequestContext requestCont requestContext.abortWith(badClientRequest()); return; } else { - String expectedCookieTokenValue = config.tokenSignatureKey.isPresent() - ? CsrfTokenUtils.signCsrfToken(csrfToken, config.tokenSignatureKey.get()) + String expectedCookieTokenValue = config.tokenSignatureKey().isPresent() + ? CsrfTokenUtils.signCsrfToken(csrfToken, config.tokenSignatureKey().get()) : csrfToken; if (!cookieToken.equals(expectedCookieTokenValue)) { LOG.debug("CSRF token value is wrong"); @@ -227,7 +227,7 @@ public void filter(ContainerRequestContext requestContext, final RestCsrfConfig config = configInstance.get(); String cookieValue = null; - if (config.tokenSignatureKey.isPresent()) { + if (config.tokenSignatureKey().isPresent()) { byte[] csrfTokenBytes = (byte[]) routing.get(CSRF_TOKEN_BYTES_KEY); if (csrfTokenBytes == null) { @@ -235,7 +235,7 @@ public void filter(ContainerRequestContext requestContext, + ", no CSRF cookie will be created"); return; } - cookieValue = CsrfTokenUtils.signCsrfToken(csrfTokenBytes, config.tokenSignatureKey.get()); + cookieValue = CsrfTokenUtils.signCsrfToken(csrfTokenBytes, config.tokenSignatureKey().get()); } else { String csrfToken = (String) routing.get(CSRF_TOKEN_KEY); @@ -258,7 +258,7 @@ public void filter(ContainerRequestContext requestContext, * @return An Optional containing the token, or an empty Optional if the token cookie is not present or is invalid */ private static String getCookieToken(RoutingContext routing, RestCsrfConfig config) { - Cookie cookie = routing.getCookie(config.cookieName); + Cookie cookie = routing.getCookie(config.cookieName()); if (cookie == null) { LOG.debug("CSRF token cookie is not set"); @@ -269,19 +269,19 @@ private static String getCookieToken(RoutingContext routing, RestCsrfConfig conf } private static boolean isCsrfTokenRequired(RoutingContext routing, RestCsrfConfig config) { - return config.createTokenPath + return config.createTokenPath() .map(value -> value.contains(routing.normalizedPath())).orElse(true); } private static void createCookie(String cookieTokenValue, RoutingContext routing, RestCsrfConfig config) { - ServerCookie cookie = new CookieImpl(config.cookieName, cookieTokenValue); - cookie.setHttpOnly(config.cookieHttpOnly); - cookie.setSecure(config.cookieForceSecure || routing.request().isSSL()); - cookie.setMaxAge(config.cookieMaxAge.toSeconds()); - cookie.setPath(config.cookiePath); - if (config.cookieDomain.isPresent()) { - cookie.setDomain(config.cookieDomain.get()); + ServerCookie cookie = new CookieImpl(config.cookieName(), cookieTokenValue); + cookie.setHttpOnly(config.cookieHttpOnly()); + cookie.setSecure(config.cookieForceSecure() || routing.request().isSSL()); + cookie.setMaxAge(config.cookieMaxAge().toSeconds()); + cookie.setPath(config.cookiePath()); + if (config.cookieDomain().isPresent()) { + cookie.setDomain(config.cookieDomain().get()); } routing.response().addCookie(cookie); } diff --git a/extensions/resteasy-reactive/rest-csrf/runtime/src/main/java/io/quarkus/csrf/reactive/runtime/CsrfTokenParameterProvider.java b/extensions/resteasy-reactive/rest-csrf/runtime/src/main/java/io/quarkus/csrf/reactive/runtime/CsrfTokenParameterProvider.java index e949a8a32806f..76b59c1474ab6 100644 --- a/extensions/resteasy-reactive/rest-csrf/runtime/src/main/java/io/quarkus/csrf/reactive/runtime/CsrfTokenParameterProvider.java +++ b/extensions/resteasy-reactive/rest-csrf/runtime/src/main/java/io/quarkus/csrf/reactive/runtime/CsrfTokenParameterProvider.java @@ -25,9 +25,9 @@ public class CsrfTokenParameterProvider { private final String csrfHeaderName; public CsrfTokenParameterProvider(RestCsrfConfig config) { - this.csrfFormFieldName = config.formFieldName; - this.csrfCookieName = config.cookieName; - this.csrfHeaderName = config.tokenHeaderName; + this.csrfFormFieldName = config.formFieldName(); + this.csrfCookieName = config.cookieName(); + this.csrfHeaderName = config.tokenHeaderName(); } /** diff --git a/extensions/resteasy-reactive/rest-csrf/runtime/src/main/java/io/quarkus/csrf/reactive/runtime/RestCsrfConfig.java b/extensions/resteasy-reactive/rest-csrf/runtime/src/main/java/io/quarkus/csrf/reactive/runtime/RestCsrfConfig.java index 5f2e4870b8319..a826c1a2a6278 100644 --- a/extensions/resteasy-reactive/rest-csrf/runtime/src/main/java/io/quarkus/csrf/reactive/runtime/RestCsrfConfig.java +++ b/extensions/resteasy-reactive/rest-csrf/runtime/src/main/java/io/quarkus/csrf/reactive/runtime/RestCsrfConfig.java @@ -4,83 +4,83 @@ import java.util.Optional; import java.util.Set; -import io.quarkus.runtime.annotations.ConfigItem; import io.quarkus.runtime.annotations.ConfigPhase; import io.quarkus.runtime.annotations.ConfigRoot; +import io.smallrye.config.ConfigMapping; +import io.smallrye.config.WithDefault; /** * Runtime configuration for CSRF Reactive Filter. */ @ConfigRoot(phase = ConfigPhase.RUN_TIME) -public class RestCsrfConfig { +@ConfigMapping(prefix = "quarkus.rest-csrf") +public interface RestCsrfConfig { /** * Form field name which keeps a CSRF token. */ - @ConfigItem(defaultValue = "csrf-token") - public String formFieldName; + @WithDefault("csrf-token") + String formFieldName(); /** * Token header which can provide a CSRF token. */ - @ConfigItem(defaultValue = "X-CSRF-TOKEN") - public String tokenHeaderName; + @WithDefault("X-CSRF-TOKEN") + String tokenHeaderName(); /** * CSRF cookie name. */ - @ConfigItem(defaultValue = "csrf-token") - public String cookieName; + @WithDefault("csrf-token") + String cookieName(); /** * CSRF cookie max age. */ - @ConfigItem(defaultValue = "2H") - public Duration cookieMaxAge; + @WithDefault("2H") + Duration cookieMaxAge(); /** * CSRF cookie path. */ - @ConfigItem(defaultValue = "/") - public String cookiePath; + @WithDefault("/") + String cookiePath(); /** * CSRF cookie domain. */ - @ConfigItem - public Optional cookieDomain; + Optional cookieDomain(); /** * If enabled the CSRF cookie will have its 'secure' parameter set to 'true' * when HTTP is used. It may be necessary when running behind an SSL terminating reverse proxy. * The cookie will always be secure if HTTPS is used even if this property is set to false. */ - @ConfigItem(defaultValue = "false") - public boolean cookieForceSecure; + @WithDefault("false") + boolean cookieForceSecure(); /** * Set the HttpOnly attribute to prevent access to the cookie via JavaScript. */ - @ConfigItem(defaultValue = "true") - public boolean cookieHttpOnly = true; + @WithDefault("true") + boolean cookieHttpOnly(); + /** * Create CSRF token only if the HTTP GET relative request path matches one of the paths configured with this property. * Use a comma to separate multiple path values. * */ - @ConfigItem - public Optional> createTokenPath; + Optional> createTokenPath(); /** * Random CSRF token size in bytes. */ - @ConfigItem(defaultValue = "16") - public int tokenSize; + @WithDefault("16") + int tokenSize(); /** * CSRF token HMAC signature key, if this key is set then it must be at least 32 characters long. */ - @ConfigItem - public Optional tokenSignatureKey; + Optional tokenSignatureKey(); /** * Verify CSRF token in the CSRF filter. @@ -95,8 +95,8 @@ public class RestCsrfConfig { * is available, has the correct {@linkplain #tokenSize} in bytes and that the Content-Type HTTP header is * either 'application/x-www-form-urlencoded' or 'multipart/form-data'. */ - @ConfigItem(defaultValue = "true") - public boolean verifyToken; + @WithDefault("true") + boolean verifyToken(); /** * Require that only 'application/x-www-form-urlencoded' or 'multipart/form-data' body is accepted for the token @@ -105,6 +105,6 @@ public class RestCsrfConfig { * This property is only effective if {@link #verifyToken} property is enabled and {@link #tokenHeaderName} is not * configured. */ - @ConfigItem(defaultValue = "true") - public boolean requireFormUrlEncoded; + @WithDefault("true") + boolean requireFormUrlEncoded(); } diff --git a/extensions/resteasy-reactive/rest-kotlin-serialization-common/deployment/pom.xml b/extensions/resteasy-reactive/rest-kotlin-serialization-common/deployment/pom.xml index dd2b30f26a1aa..34164d680d281 100644 --- a/extensions/resteasy-reactive/rest-kotlin-serialization-common/deployment/pom.xml +++ b/extensions/resteasy-reactive/rest-kotlin-serialization-common/deployment/pom.xml @@ -99,9 +99,6 @@ ${project.version} - - -AlegacyConfigRoot=true - diff --git a/extensions/resteasy-reactive/rest-kotlin-serialization-common/runtime/pom.xml b/extensions/resteasy-reactive/rest-kotlin-serialization-common/runtime/pom.xml index 9d1be7af540b7..ee8e4d0d1d51c 100644 --- a/extensions/resteasy-reactive/rest-kotlin-serialization-common/runtime/pom.xml +++ b/extensions/resteasy-reactive/rest-kotlin-serialization-common/runtime/pom.xml @@ -95,9 +95,6 @@ ${project.version} - - -AlegacyConfigRoot=true - diff --git a/extensions/resteasy-reactive/rest-kotlin-serialization-common/runtime/src/main/java/io/quarkus/resteasy/reactive/kotlin/serialization/common/runtime/JsonConfig.java b/extensions/resteasy-reactive/rest-kotlin-serialization-common/runtime/src/main/java/io/quarkus/resteasy/reactive/kotlin/serialization/common/runtime/JsonConfig.java index c3a505a27ee66..1fa1027ddfb4c 100644 --- a/extensions/resteasy-reactive/rest-kotlin-serialization-common/runtime/src/main/java/io/quarkus/resteasy/reactive/kotlin/serialization/common/runtime/JsonConfig.java +++ b/extensions/resteasy-reactive/rest-kotlin-serialization-common/runtime/src/main/java/io/quarkus/resteasy/reactive/kotlin/serialization/common/runtime/JsonConfig.java @@ -1,47 +1,46 @@ package io.quarkus.resteasy.reactive.kotlin.serialization.common.runtime; import java.util.Optional; -import java.util.StringJoiner; import io.quarkus.runtime.annotations.ConfigGroup; -import io.quarkus.runtime.annotations.ConfigItem; +import io.smallrye.config.WithDefault; @ConfigGroup -public class JsonConfig { +public interface JsonConfig { /** * Removes JSON specification restriction on * special floating-point values such as `NaN` and `Infinity` and enables their serialization and deserialization. * When enabling it, please ensure that the receiving party will be able to encode and decode these special values. */ - @ConfigItem(defaultValue = "false") - public boolean allowSpecialFloatingPointValues = false; + @WithDefault("false") + boolean allowSpecialFloatingPointValues(); /** * Enables structured objects to be serialized as map keys by * changing serialized form of the map from JSON object (key-value pairs) to flat array like `[k1, v1, k2, v2]`. */ - @ConfigItem(defaultValue = "false") - public boolean allowStructuredMapKeys = false; + @WithDefault("false") + boolean allowStructuredMapKeys(); /** * Name of the class descriptor property for polymorphic serialization. */ - @ConfigItem(defaultValue = "type") - public String classDiscriminator = "type"; + @WithDefault("type") + String classDiscriminator(); /** * Enables coercing incorrect JSON values to the default property value in the following cases: * 1. JSON value is `null` but property type is non-nullable. * 2. Property type is an enum type, but JSON value contains unknown enum member. */ - @ConfigItem(defaultValue = "false") - public boolean coerceInputValues = false; + @WithDefault("false") + boolean coerceInputValues(); /** * Specifies whether default values of Kotlin properties should be encoded. */ - @ConfigItem(defaultValue = "true") - public boolean encodeDefaults = true; + @WithDefault("true") + boolean encodeDefaults(); /** * Specifies whether `null` values should be encoded for nullable properties and must be present in JSON object @@ -52,15 +51,15 @@ public class JsonConfig { *

* {@code true} by default. */ - @ConfigItem(defaultValue = "true") - public boolean explicitNulls = true; + @WithDefault("true") + boolean explicitNulls(); /** * Specifies whether encounters of unknown properties in the input JSON * should be ignored instead of throwing [SerializationException]. */ - @ConfigItem(defaultValue = "false") - public boolean ignoreUnknownKeys = false; + @WithDefault("false") + boolean ignoreUnknownKeys(); /** * Removes JSON specification restriction (RFC-4627) and makes parser @@ -70,20 +69,20 @@ public class JsonConfig { * Its relaxations can be expanded in the future, so that lenient parser becomes even more * permissive to invalid value in the input, replacing them with defaults. */ - @ConfigItem(defaultValue = "false") - public boolean isLenient = false; + @WithDefault("false") + boolean isLenient(); /** * Specifies whether resulting JSON should be pretty-printed. */ - @ConfigItem(defaultValue = "false") - public boolean prettyPrint = false; + @WithDefault("false") + boolean prettyPrint(); /** * Specifies indent string to use with [prettyPrint] mode */ - @ConfigItem(defaultValue = " ") - public String prettyPrintIndent = " "; + @WithDefault(" ") + String prettyPrintIndent(); /** * Specifies whether Json instance makes use of [JsonNames] annotation. @@ -91,15 +90,15 @@ public class JsonConfig { * Disabling this flag when one does not use [JsonNames] at all may sometimes result in better performance, * particularly when a large count of fields is skipped with [ignoreUnknownKeys]. */ - @ConfigItem(defaultValue = "true") - public boolean useAlternativeNames = true; + @WithDefault("true") + boolean useAlternativeNames(); /** * Switches polymorphic serialization to the default array format. * This is an option for legacy JSON format and should not be generally used. */ - @ConfigItem(defaultValue = "false") - public boolean useArrayPolymorphism = false; + @WithDefault("false") + boolean useArrayPolymorphism(); /** * Specifies the {@code JsonNamingStrategy} that should be used for all properties in classes for serialization and @@ -120,44 +119,24 @@ public class JsonConfig { * * */ - @ConfigItem(name = "naming-strategy") - public Optional namingStrategy; + Optional namingStrategy(); /** * Specifies if the enum values should be decoded case insensitively. */ - @ConfigItem(defaultValue = "false") - public boolean decodeEnumsCaseInsensitive = false; + @WithDefault("false") + boolean decodeEnumsCaseInsensitive(); /** * Specifies if trailing comma is allowed. */ - @ConfigItem(defaultValue = "false") - public boolean allowTrailingComma = false; + @WithDefault("false") + boolean allowTrailingComma(); /** * Allows parser to accept C/Java-style comments in JSON input. */ - @ConfigItem(defaultValue = "false") - public boolean allowComments = false; - - @Override - public String toString() { - return new StringJoiner(", ", JsonConfig.class.getSimpleName() + "[", "]") - .add("encodeDefaults=" + encodeDefaults) - .add("ignoreUnknownKeys=" + ignoreUnknownKeys) - .add("isLenient=" + isLenient) - .add("allowStructuredMapKeys=" + allowStructuredMapKeys) - .add("prettyPrint=" + prettyPrint) - .add("prettyPrintIndent='" + prettyPrintIndent + "'") - .add("coerceInputValues=" + coerceInputValues) - .add("useArrayPolymorphism=" + useArrayPolymorphism) - .add("classDiscriminator='" + classDiscriminator + "'") - .add("allowSpecialFloatingPointValues=" + allowSpecialFloatingPointValues) - .add("useAlternativeNames=" + useAlternativeNames) - .add("decodeEnumsCaseInsensitive=" + decodeEnumsCaseInsensitive) - .add("allowTrailingComma=" + allowTrailingComma) - .add("allowComments=" + allowComments) - .toString(); - } + @WithDefault("false") + boolean allowComments(); + } diff --git a/extensions/resteasy-reactive/rest-kotlin-serialization-common/runtime/src/main/java/io/quarkus/resteasy/reactive/kotlin/serialization/common/runtime/KotlinSerializationConfig.java b/extensions/resteasy-reactive/rest-kotlin-serialization-common/runtime/src/main/java/io/quarkus/resteasy/reactive/kotlin/serialization/common/runtime/KotlinSerializationConfig.java index 7a9aa129dbec8..dc3b4be3e25d4 100644 --- a/extensions/resteasy-reactive/rest-kotlin-serialization-common/runtime/src/main/java/io/quarkus/resteasy/reactive/kotlin/serialization/common/runtime/KotlinSerializationConfig.java +++ b/extensions/resteasy-reactive/rest-kotlin-serialization-common/runtime/src/main/java/io/quarkus/resteasy/reactive/kotlin/serialization/common/runtime/KotlinSerializationConfig.java @@ -1,25 +1,16 @@ package io.quarkus.resteasy.reactive.kotlin.serialization.common.runtime; -import java.util.StringJoiner; - -import io.quarkus.runtime.annotations.ConfigItem; import io.quarkus.runtime.annotations.ConfigPhase; import io.quarkus.runtime.annotations.ConfigRoot; +import io.smallrye.config.ConfigMapping; -@ConfigRoot(name = KotlinSerializationConfig.CONFIG_NAME, phase = ConfigPhase.BUILD_AND_RUN_TIME_FIXED) -public class KotlinSerializationConfig { - public static final String CONFIG_NAME = "kotlin-serialization"; +@ConfigRoot(phase = ConfigPhase.BUILD_AND_RUN_TIME_FIXED) +@ConfigMapping(prefix = KotlinSerializationConfig.CONFIG_PREFIX) +public interface KotlinSerializationConfig { + public static final String CONFIG_PREFIX = "quarkus.kotlin-serialization"; /** * Configuration element for serializing to json */ - @ConfigItem(name = "json") - public JsonConfig json = new JsonConfig(); - - @Override - public String toString() { - return new StringJoiner(", ", KotlinSerializationConfig.class.getSimpleName() + "[", "]") - .add("json=" + json) - .toString(); - } + public JsonConfig json(); } diff --git a/extensions/resteasy-reactive/rest-kotlin-serialization-common/runtime/src/main/kotlin/io/quarkus/resteasy/reactive/kotlin/serialization/common/runtime/JsonProducer.kt b/extensions/resteasy-reactive/rest-kotlin-serialization-common/runtime/src/main/kotlin/io/quarkus/resteasy/reactive/kotlin/serialization/common/runtime/JsonProducer.kt index 89dc0289b1104..83f568aa16676 100644 --- a/extensions/resteasy-reactive/rest-kotlin-serialization-common/runtime/src/main/kotlin/io/quarkus/resteasy/reactive/kotlin/serialization/common/runtime/JsonProducer.kt +++ b/extensions/resteasy-reactive/rest-kotlin-serialization-common/runtime/src/main/kotlin/io/quarkus/resteasy/reactive/kotlin/serialization/common/runtime/JsonProducer.kt @@ -25,22 +25,22 @@ class JsonProducer { configuration: KotlinSerializationConfig, @All customizers: java.util.List ) = Json { - allowSpecialFloatingPointValues = configuration.json.allowSpecialFloatingPointValues - allowStructuredMapKeys = configuration.json.allowStructuredMapKeys - classDiscriminator = configuration.json.classDiscriminator - coerceInputValues = configuration.json.coerceInputValues - encodeDefaults = configuration.json.encodeDefaults - explicitNulls = configuration.json.explicitNulls - ignoreUnknownKeys = configuration.json.ignoreUnknownKeys - isLenient = configuration.json.isLenient - prettyPrint = configuration.json.prettyPrint - prettyPrintIndent = configuration.json.prettyPrintIndent - useAlternativeNames = configuration.json.useAlternativeNames - useArrayPolymorphism = configuration.json.useArrayPolymorphism - decodeEnumsCaseInsensitive = configuration.json.decodeEnumsCaseInsensitive - allowTrailingComma = configuration.json.allowTrailingComma + allowSpecialFloatingPointValues = configuration.json().allowSpecialFloatingPointValues() + allowStructuredMapKeys = configuration.json().allowStructuredMapKeys() + classDiscriminator = configuration.json().classDiscriminator() + coerceInputValues = configuration.json().coerceInputValues() + encodeDefaults = configuration.json().encodeDefaults() + explicitNulls = configuration.json().explicitNulls() + ignoreUnknownKeys = configuration.json().ignoreUnknownKeys() + isLenient = configuration.json().isLenient() + prettyPrint = configuration.json().prettyPrint() + prettyPrintIndent = configuration.json().prettyPrintIndent() + useAlternativeNames = configuration.json().useAlternativeNames() + useArrayPolymorphism = configuration.json().useArrayPolymorphism() + decodeEnumsCaseInsensitive = configuration.json().decodeEnumsCaseInsensitive() + allowTrailingComma = configuration.json().allowTrailingComma() - configuration.json.namingStrategy.ifPresent { strategy -> + configuration.json().namingStrategy().ifPresent { strategy -> loadStrategy(this, strategy, this@JsonProducer) } val sortedCustomizers = sortCustomizersInDescendingPriorityOrder(customizers) diff --git a/extensions/resteasy-reactive/rest-kotlin-serialization-common/runtime/src/test/java/io/quarkus/kotlin/serialization/JsonConfigTest.java b/extensions/resteasy-reactive/rest-kotlin-serialization-common/runtime/src/test/java/io/quarkus/kotlin/serialization/JsonConfigTest.java index dac69afa1e27c..2d1a0e209b8e0 100644 --- a/extensions/resteasy-reactive/rest-kotlin-serialization-common/runtime/src/test/java/io/quarkus/kotlin/serialization/JsonConfigTest.java +++ b/extensions/resteasy-reactive/rest-kotlin-serialization-common/runtime/src/test/java/io/quarkus/kotlin/serialization/JsonConfigTest.java @@ -22,7 +22,7 @@ public void ensureJsonCoverage() { .map(f -> f.getName()) .filter(n -> !EXCLUSIONS.contains(n)) .collect(Collectors.toSet())); - kotlinFields.removeAll(Arrays.stream(JsonConfig.class.getDeclaredFields()) + kotlinFields.removeAll(Arrays.stream(JsonConfig.class.getDeclaredMethods()) .map(f -> f.getName()) .collect(Collectors.toSet())); assertTrue(kotlinFields.isEmpty(), "Make sure all the fields of " + JsonConfiguration.class.getName()