Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3.4.3 backports 1 #36416

Merged
merged 14 commits into from
Oct 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions bom/application/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<jandex.version>3.1.3</jandex.version>
<javax.annotation-api.version>1.3.2</javax.annotation-api.version>
<javax.inject.version>1</javax.inject.version>
<parsson.version>1.1.2</parsson.version>
<parsson.version>1.1.4</parsson.version>
<resteasy-microprofile.version>2.1.4.Final</resteasy-microprofile.version>
<resteasy-spring-web.version>3.0.2.Final</resteasy-spring-web.version>
<resteasy.version>6.2.5.Final</resteasy.version>
Expand Down Expand Up @@ -142,7 +142,7 @@
<infinispan.version>14.0.17.Final</infinispan.version>
<infinispan.protostream.version>4.6.5.Final</infinispan.protostream.version>
<caffeine.version>3.1.5</caffeine.version>
<netty.version>4.1.97.Final</netty.version>
<netty.version>4.1.100.Final</netty.version>
<brotli4j.version>1.12.0</brotli4j.version>
<reactive-streams.version>1.0.4</reactive-streams.version>
<jboss-logging.version>3.5.3.Final</jboss-logging.version>
Expand Down
24 changes: 24 additions & 0 deletions core/deployment/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,30 @@
</executions>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>com.gradle</groupId>
<artifactId>gradle-enterprise-maven-extension</artifactId>
<configuration>
<gradleEnterprise>
<!--
For now, do not store the output of the maven-compiler-plugin as we generate the config doc.
Ideally, we would register them as additional output but their organization is too messy for now.
-->
<plugins combine.children="append">
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<outputs>
<notCacheableBecause>the extension config doc generation tool shares data across all extensions</notCacheableBecause>
</outputs>
</plugin>
</plugins>
</gradleEnterprise>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>

<profiles>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1018,28 +1018,40 @@ private Converter<?> getConverter(SmallRyeConfig config, Field field, ConverterT
*/
private Set<String> getAllProperties(final Set<String> registeredRoots) {
Set<String> properties = new HashSet<>();

// Get all properties, including the ones generated by interceptors, but these do not include profiles
for (String property : config.getPropertyNames()) {
properties.add(property);
}

Set<String> propertiesToRemove = new HashSet<>();
Set<String> propertiesToAdd = new HashSet<>();

// Get properties per source to collect profiled properties and exclude properties that are build related
for (ConfigSource configSource : config.getConfigSources()) {
if (configSource instanceof SysPropConfigSource || configSource instanceof EnvConfigSource
|| "PropertiesConfigSource[source=Build system]".equals(configSource.getName())) {
for (String property : configSource.getPropertyNames()) {
NameIterator ni = new NameIterator(property);
if (ni.hasNext() && PropertiesUtil.isPropertyInRoot(registeredRoots, ni)) {
properties.add(property);
propertiesToAdd.add(property);
} else {
properties.remove(property);
propertiesToRemove.add(property);
if (configSource instanceof EnvConfigSource) {
properties.remove(StringUtil.toLowerCaseAndDotted(property));
propertiesToRemove.add(StringUtil.toLowerCaseAndDotted(property));
}
}
}
} else {
properties.addAll(configSource.getPropertyNames());
propertiesToAdd.addAll(configSource.getPropertyNames());
}
}

// A property may exist in an excluded source and an include source. We don't have a way to know, so we
// just remove the excluded ones and add the ones to be included, so the property is back there again
properties.removeAll(propertiesToRemove);
properties.addAll(propertiesToAdd);

return properties;
}

Expand Down
24 changes: 24 additions & 0 deletions core/runtime/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,30 @@
</executions>
</plugin>
</plugins>
<pluginManagement>
<plugins>
<plugin>
<groupId>com.gradle</groupId>
<artifactId>gradle-enterprise-maven-extension</artifactId>
<configuration>
<gradleEnterprise>
<!--
For now, do not store the output of the maven-compiler-plugin as we generate the config doc.
Ideally, we would register them as additional output but their organization is too messy for now.
-->
<plugins combine.children="append">
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<outputs>
<notCacheableBecause>the extension config doc generation tool shares data across all extensions</notCacheableBecause>
</outputs>
</plugin>
</plugins>
</gradleEnterprise>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>

</project>
5 changes: 5 additions & 0 deletions docs/src/main/asciidoc/ansible.adoc
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
////
This guide is maintained in the main Quarkus repository
and pull requests should be submitted there:
https://github.com/quarkusio/quarkus/tree/main/docs/src/main/asciidoc
////
= Automate Quarkus deployment with Ansible
include::_attributes.adoc[]
:categories: command-line
Expand Down
1 change: 1 addition & 0 deletions docs/src/main/asciidoc/cdi-reference.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ https://github.com/quarkusio/quarkus/tree/main/docs/src/main/asciidoc
= Contexts and Dependency Injection
include::_attributes.adoc[]
:categories: core
:keywords: arc
:summary: Go more in depth into the Quarkus implementation of CDI.
:numbered:
:sectnums:
Expand Down
71 changes: 36 additions & 35 deletions docs/src/main/asciidoc/cdi.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ https://github.com/quarkusio/quarkus/tree/main/docs/src/main/asciidoc
= Introduction to Contexts and Dependency Injection (CDI)
include::_attributes.adoc[]
:categories: core
:keywords: qualifier event interceptor observer arc
:summary: Quarkus DI solution is based on the [Jakarta Contexts and Dependency Injection 4.0](https://jakarta.ee/specifications/cdi/4.0/jakarta-cdi-spec-4.0.html) specification. This guide explains the basics of CDI.
:numbered:
:sectnums:
Expand All @@ -28,7 +29,7 @@ It creates and destroys the instances of beans, associates the instances with a

An application developer can focus on the business logic rather than finding out "where and how" to obtain a fully initialized component with all of its dependencies.

NOTE: You've probably heard of the _inversion of control_ (IoC) programming principle. Dependency injection is one of the implementation techniques of IoC.
NOTE: You've probably heard of the _inversion of control_ (IoC) programming principle. Dependency injection is one of the implementation techniques of IoC.

== What does a bean look like?

Expand All @@ -47,9 +48,9 @@ public class Translator {

@Inject
Dictionary dictionary; <2>

@Counted <3>
String translate(String sentence) {
String translate(String sentence) {
// ...
}
}
Expand Down Expand Up @@ -86,8 +87,8 @@ public class Translator {

@Inject
Instance<Dictionary> dictionaries; <1>
String translate(String sentence) {

String translate(String sentence) {
for (Dictionary dict : dictionaries) { <2>
// ...
}
Expand Down Expand Up @@ -122,11 +123,11 @@ public class Translator {
}
}
----
<1> This is a constructor injection.
In fact, this code would not work in regular CDI implementations where a bean with a normal scope must always declare a no-args constructor and the bean constructor must be annotated with `@Inject`.
<1> This is a constructor injection.
In fact, this code would not work in regular CDI implementations where a bean with a normal scope must always declare a no-args constructor and the bean constructor must be annotated with `@Inject`.
However, in Quarkus we detect the absence of no-args constructor and "add" it directly in the bytecode.
It's also not necessary to add `@Inject` if there is only one constructor present.
<2> An initializer method must be annotated with `@Inject`.
<2> An initializer method must be annotated with `@Inject`.
<3> An initializer may accept multiple parameters - each one is an injection point.

== You talked about some qualifiers?
Expand Down Expand Up @@ -155,7 +156,7 @@ The qualifiers of a bean are declared by annotating the bean class or producer m
@ApplicationScoped
public class SuperiorTranslator extends Translator {

String translate(String sentence) {
String translate(String sentence) {
// ...
}
}
Expand All @@ -180,11 +181,11 @@ You can use all the built-in scopes mentioned by the specification except for `j

[options="header",cols="1,1"]
|===
|Annotation |Description
|Annotation |Description
//----------------------
|`@jakarta.enterprise.context.ApplicationScoped` | A single bean instance is used for the application and shared among all injection points. The instance is created lazily, i.e. once a method is invoked upon the <<client_proxies, client proxy>>.
|`@jakarta.enterprise.context.ApplicationScoped` | A single bean instance is used for the application and shared among all injection points. The instance is created lazily, i.e. once a method is invoked upon the <<client_proxies, client proxy>>.
|`@jakarta.inject.Singleton` | Just like `@ApplicationScoped` except that no client proxy is used. The instance is created when an injection point that resolves to a @Singleton bean is being injected.
|`@jakarta.enterprise.context.RequestScoped` | The bean instance is associated with the current _request_ (usually an HTTP request).
|`@jakarta.enterprise.context.RequestScoped` | The bean instance is associated with the current _request_ (usually an HTTP request).
|`@jakarta.enterprise.context.Dependent` | This is a pseudo-scope. The instances are not shared and every injection point spawns a new instance of the dependent bean. The lifecycle of dependent bean is bound to the bean injecting it - it will be created and destroyed along with the bean injecting it.
|`@jakarta.enterprise.context.SessionScoped` | This scope is backed by a `jakarta.servlet.http.HttpSession` object. It's only available if the `quarkus-undertow` extension is used.
|===
Expand Down Expand Up @@ -217,23 +218,23 @@ Indeed, the https://jakarta.ee/specifications/cdi/4.0/jakarta-cdi-spec-4.0.html#
A client proxy is basically an object that delegates all method invocations to a target bean instance.
It's a container construct that implements `io.quarkus.arc.ClientProxy` and extends the bean class.

IMPORTANT: Client proxies only delegate method invocations. So never read or write a field of a normal scoped bean, otherwise you will work with non-contextual or stale data.
IMPORTANT: Client proxies only delegate method invocations. So never read or write a field of a normal scoped bean, otherwise you will work with non-contextual or stale data.

.Generated Client Proxy Example
[source,java]
----
@ApplicationScoped
class Translator {

String translate(String sentence) {
String translate(String sentence) {
// ...
}
}

// The client proxy class is generated and looks like...
class Translator_ClientProxy extends Translator { <1>

String translate(String sentence) {
String translate(String sentence) {
// Find the correct translator instance...
Translator translator = getTranslatorInstanceFromTheApplicationContext();
// And delegate the method invocation...
Expand All @@ -247,10 +248,10 @@ Client proxies allow for:

* Lazy instantiation - the instance is created once a method is invoked upon the proxy.
* Ability to inject a bean with "narrower" scope to a bean with "wider" scope; i.e. you can inject a `@RequestScoped` bean into an `@ApplicationScoped` bean.
* Circular dependencies in the dependency graph. Having circular dependencies is often an indication that a redesign should be considered, but sometimes it's inevitable.
* Circular dependencies in the dependency graph. Having circular dependencies is often an indication that a redesign should be considered, but sometimes it's inevitable.
* In rare cases it's practical to destroy the beans manually. A direct injected reference would lead to a stale bean instance.


== OK. You said that there are several kinds of beans?

Yes. In general, we distinguish:
Expand All @@ -273,7 +274,7 @@ public class Producers {

@Produces <1>
double pi = Math.PI; <2>

@Produces <3>
List<String> names() {
List<String> names = new ArrayList<>();
Expand All @@ -289,26 +290,26 @@ public class Consumer {

@Inject
double pi;

@Inject
List<String> names;
// ...
}

// ...
}
----
<1> The container analyses the field annotations to build a bean metadata.
The _type_ is used to build the set of bean types.
The _type_ is used to build the set of bean types.
In this case, it will be `double` and `java.lang.Object`.
No scope annotation is declared and so it's defaulted to `@Dependent`.
<2> The container will read this field when creating the bean instance.
<3> The container analyses the method annotations to build a bean metadata.
The _return type_ is used to build the set of bean types.
The _return type_ is used to build the set of bean types.
In this case, it will be `List<String>`, `Collection<String>`, `Iterable<String>` and `java.lang.Object`.
No scope annotation is declared and so it's defaulted to `@Dependent`.
<4> The container will call this method when creating the bean instance.

There's more about producers.
You can declare qualifiers, inject dependencies into the producer methods parameters, etc.
There's more about producers.
You can declare qualifiers, inject dependencies into the producer methods parameters, etc.
You can read more about producers for example in the https://docs.jboss.org/weld/reference/latest/en-US/html/producermethods.html[Weld docs, window="_blank"].

== OK, injection looks cool. What other services are provided?
Expand All @@ -330,7 +331,7 @@ public class Translator {
void init() {
// ...
}

@PreDestroy <2>
void destroy() {
// ...
Expand All @@ -345,7 +346,7 @@ TIP: It's a good practice to keep the logic in the callbacks "without side effec
[[interceptors]]
=== Interceptors

Interceptors are used to separate cross-cutting concerns from business logic.
Interceptors are used to separate cross-cutting concerns from business logic.
There is a separate specification - Java Interceptors - that defines the basic programming model and semantics.

.Simple Interceptor Binding Example
Expand Down Expand Up @@ -392,11 +393,11 @@ public class LoggingInterceptor {
// ...log after
return ret;
}

}
----
<1> The interceptor binding annotation is used to bind our interceptor to a bean. Simply annotate a bean class with `@Logged`, as in the following example.
<2> `Priority` enables the interceptor and affects the interceptor ordering. Interceptors with smaller priority values are called first.
<2> `Priority` enables the interceptor and affects the interceptor ordering. Interceptors with smaller priority values are called first.
<3> Marks an interceptor component.
<4> An interceptor may inject dependencies.
<5> `AroundInvoke` denotes a method that interposes on business methods.
Expand Down Expand Up @@ -448,7 +449,7 @@ public class LargeTxAccount implements Account { <3>
@Any
@Delegate
Account delegate; <4>

@Inject
LogService logService; <5>

Expand All @@ -458,10 +459,10 @@ public class LargeTxAccount implements Account { <3>
logService.logWithdrawal(delegate, amount);
}
}

}
----
<1> `@Priority` enables the decorator. Decorators with smaller priority values are called first.
<1> `@Priority` enables the decorator. Decorators with smaller priority values are called first.
<2> `@Decorator` marks a decorator component.
<3> The set of decorated types includes all bean types which are Java interfaces, except for `java.io.Serializable`.
<4> Each decorator must declare exactly one _delegate injection point_. The decorator applies to beans that are assignable to this delegate injection point.
Expand All @@ -471,7 +472,7 @@ public class LargeTxAccount implements Account { <3>
NOTE: Instances of decorators are dependent objects of the bean instance they intercept, i.e. a new decorator instance is created for each intercepted bean.

=== Events and Observers

Beans may also produce and consume events to interact in a completely decoupled fashion.
Any Java object can serve as an event payload.
The optional qualifiers act as topic selectors.
Expand Down
Loading
Loading