Skip to content

Commit

Permalink
Merge pull request #27963 from mkouba/issue-22101-next
Browse files Browse the repository at this point in the history
Remove deprecated annotations from the io.quarkus.arc.config package
  • Loading branch information
mkouba authored Sep 20, 2022
2 parents dfb830c + db7aa21 commit e7ae963
Show file tree
Hide file tree
Showing 53 changed files with 285 additions and 3,286 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,11 @@
import io.smallrye.config.ConfigMappingMetadata;

public class ConfigMappingUtils {

public static final DotName CONFIG_MAPPING_NAME = DotName.createSimple(ConfigMapping.class.getName());

private static final DotName OPTIONAL = DotName.createSimple(Optional.class.getName());

private ConfigMappingUtils() {
}

Expand Down Expand Up @@ -109,7 +112,12 @@ static void processConfigClass(
// For implicit converters
for (ClassInfo classInfo : mappingsInfo) {
for (MethodInfo method : classInfo.methods()) {
reflectiveClasses.produce(new ReflectiveClassBuildItem(true, false, method.returnType().name().toString()));
Type type = method.returnType();
if (type.name().equals(OPTIONAL)) {
// E.g. Optional<Foo>
type = type.asParameterizedType().arguments().get(0);
}
reflectiveClasses.produce(new ReflectiveClassBuildItem(true, false, type.name().toString()));
}
}

Expand Down
219 changes: 1 addition & 218 deletions docs/src/main/asciidoc/config-mappings.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -552,221 +552,4 @@ class AppConfigTest {
}
----

NOTE: Nested elements need to be spied individually by Mockito.

[[config-properties]]
== [.line-through]#`@ConfigProperties`# (Deprecated)

IMPORTANT: This feature will be removed soon, please update your code base and use `@ConfigMapping` instead.

The `@io.quarkus.arc.config.ConfigProperties` annotation is able to group multiple related configuration values in its
own class:

[source,java]
----
package org.acme.config;
import io.quarkus.arc.config.ConfigProperties;
import java.util.Optional;
@ConfigProperties(prefix = "greeting") <1>
public class GreetingConfiguration {
private String message;
private String suffix = "!"; <2>
private Optional<String> name;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getSuffix() {
return suffix;
}
public void setSuffix(String suffix) {
this.suffix = suffix;
}
public Optional<String> getName() {
return name;
}
public void setName(Optional<String> name) {
this.name = name;
}
}
----
<1> `prefix` is optional. If not set then the prefix to be used will be determined by the class name. In this case it
would still be `greeting` (since the `Configuration` suffix is removed). If the class were named
`GreetingExtraConfiguration` then the resulting default prefix would be `greeting-extra`.
<2> `!` will be the default value if `greeting.suffix` is not set.

Inject the `GreetingResource` with CDI `@Inject`:

[source,java]
----
@Inject
GreetingConfiguration greetingConfiguration;
----

Another alternative style provided by Quarkus is to create `GreetingConfiguration` as an interface:

[source,java]
----
package org.acme.config;
import io.quarkus.arc.config.ConfigProperties;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import java.util.Optional;
@ConfigProperties(prefix = "greeting")
public interface GreetingConfiguration {
@ConfigProperty(name = "message") <1>
String message();
@ConfigProperty(defaultValue = "!")
String getSuffix(); <2>
Optional<String> getName(); <3>
}
----
<1> The `@ConfigProperty` annotation is needed because the name of the configuration property that the method
corresponds does not follow the getter method naming conventions.
<2> In this case since `name` is not set, the corresponding property will be `greeting.suffix`.
<3> It is unnecessary to specify the `@ConfigProperty` annotation because the method name follows the getter method
naming conventions (`greeting.name` being the corresponding property) and no default value is required.

When using `@ConfigProperties` on a class or an interface, if the value of one of its fields is not provided, the
application startup will fail, and a `javax.enterprise.inject.spi.DeploymentException` will be thrown. This does not
apply to `Optional` fields and fields with a default value.

=== Additional notes on @ConfigProperties

When using a regular class annotated with `@ConfigProperties` the class doesn't necessarily have to declare getters and
setters. Having simple public non-final fields is valid as well.

Furthermore, the configuration classes support nested object configuration. Suppose there was a need to have an extra
layer of greeting configuration named `content` that would contain a few fields:

[source,java]
----
@ConfigProperties(prefix = "greeting")
public class GreetingConfiguration {
public String message;
public String suffix = "!";
public Optional<String> name;
public ContentConfig content; <1>
public static class ContentConfig {
public Integer prizeAmount;
public List<String> recipients;
}
}
----
<1> The name of the field (not the class name) will determine the name of the properties that are bound to the object.

Setting the properties would occur in the normal manner:

.application.properties
[source,properties]
----
greeting.message = hello
greeting.name = quarkus
greeting.content.prize-amount=10
greeting.content.recipients=Jane,John
----

Furthermore, classes annotated with `@ConfigProperties` can be annotated with Bean Validation annotations:

[source,java]
----
@ConfigProperties(prefix = "greeting")
public class GreetingConfiguration {
@Size(min = 20)
public String message;
public String suffix = "!";
}
----

WARNING: For validation to work, the `quarkus-hibernate-validator` extension is required.

=== Using same ConfigProperties with different prefixes

Quarkus also supports the use of the same `@ConfigProperties` object with different prefixes for each injection point
using the `io.quarkus.arc.config.@ConfigPrefix` annotation. If `GreetingConfiguration` from above needs to be used for
both the `greeting` prefix and the `other` prefix:

[source,java]
----
@ConfigProperties(prefix = "greeting")
public class GreetingConfiguration {
@Size(min = 20)
public String message;
public String suffix = "!";
}
----

[source,java]
----
@ApplicationScoped
public class SomeBean {
@Inject <1>
GreetingConfiguration greetingConfiguration;
@ConfigPrefix("other") <2>
GreetingConfiguration otherConfiguration;
}
----
<1> At this injection point `greetingConfiguration` will use the `greeting` prefix since that is what has been defined
on `@ConfigProperties`.
<2> At this injection point `otherConfiguration` will use the `other` prefix from `@ConfigPrefix` instead of the
`greeting` prefix. Notice that in this case `@Inject` is not required.

=== Combining ConfigProperties with build time conditions

Quarkus allows you to define conditions evaluated at build time (`@IfBuildProfile`, `@UnlessBuildProfile`,
`@IfBuildProperty` and `@UnlessBuildProperty`) to enable or not the annotations `@ConfigProperties` and `@ConfigPrefix`
which gives you a very flexible way to map your configuration.

Let's assume that the configuration of a service is mapped thanks to a `@ConfigProperties` and you don't need this part
of the configuration for your tests as it will be mocked, in that case you can define a build time condition like in
the next example:

`ServiceConfiguration.java`
[source,java]
----
@UnlessBuildProfile("test") <1>
@ConfigProperties
public class ServiceConfiguration {
public String user;
public String password;
}
----
<1> The annotation `@ConfigProperties` is considered if and only if the active profile is not `test`.

`SomeBean.java`
[source,java]
----
@ApplicationScoped
public class SomeBean {
@Inject
Instance<ServiceConfiguration> serviceConfiguration; <1>
}
----
<1> As the configuration of the service could be missing, we need to use `Instance<ServiceConfiguration>` as type at
the injection point.
NOTE: Nested elements need to be spied individually by Mockito.
2 changes: 1 addition & 1 deletion docs/src/main/asciidoc/spring-boot-properties.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ https://github.com/quarkusio/quarkus/tree/main/docs/src/main/asciidoc
include::./attributes.adoc[]

If you prefer to use Spring Boot `@ConfigurationProperties` annotated class to access application properties instead of
a Quarkus native `@ConfigProperties` or a MicroProfile `@ConfigProperty` approach, you can do that with this extension.
<<config-mappings.adoc#config-mappings,`@ConfigMapping`>> or a MicroProfile `@ConfigProperty` approach, you can do that with this extension.

IMPORTANT: Spring Boot `@ConfigurationProperties` has a few limitations. For instance, `Map` injection is not
supported. Consider using xref:config-mappings.adoc[Mapping configuration to objects].
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import java.util.Optional;
import java.util.Set;

import io.quarkus.arc.config.ConfigProperties;
import io.quarkus.deployment.index.IndexDependencyConfig;
import io.quarkus.runtime.annotations.ConfigDocMapKey;
import io.quarkus.runtime.annotations.ConfigDocSection;
Expand Down Expand Up @@ -71,21 +70,13 @@ public class ArcConfig {

/**
* If set to true, the build fails if a private method that is neither an observer nor a producer, is annotated with an
* interceptor
* binding.
* interceptor binding.
* An example of this is the use of {@code Transactional} on a private method of a bean.
* If set to false, Quarkus simply logs a warning that the annotation will be ignored.
*/
@ConfigItem(defaultValue = "false")
public boolean failOnInterceptedPrivateMethod;

/**
* The default naming strategy for {@link ConfigProperties.NamingStrategy}. The allowed values are determined
* by that enum
*/
@ConfigItem(defaultValue = "kebab-case")
public ConfigProperties.NamingStrategy configPropertiesDefaultNamingStrategy;

/**
* The list of selected alternatives for an application.
* <p>
Expand Down
Loading

0 comments on commit e7ae963

Please sign in to comment.