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

[pull] main from quarkusio:main #42

Merged
merged 13 commits into from
Nov 27, 2024
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
28 changes: 9 additions & 19 deletions docs/src/main/asciidoc/getting-started-testing.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1241,25 +1241,15 @@ public @interface WithRepeatableTestResource {
While test resources provided by `@QuarkusTestResource` are available either globally or restricted to the annotated test class (`restrictToAnnotatedClass`), the annotation `@WithTestResources` allows to additionally group tests by test resources for execution.
`@WithTestResources` has a `scope` property that takes a `TestResourceScope` enum value:

- `TestResourceScope.MATCHING_RESOURCES` (default) +
Quarkus will group tests with the same test resources and run them together. After a group has been executed, all test resources will be stopped, and the next group will be executed.
- `TestResourceScope.RESTRICTED_TO_CLASS` +
The test resource is available only for the annotated test class and will be stopped after the test class has been executed. This is equivalent to using @QuarkusTestResource with restrictToAnnotatedClass = true.
- `TestResourceScope.GLOBAL` +
The test resource is available globally.
This is equivalent to using `@QuarkusTestResource` with `restrictToAnnotatedClass = false`.

NOTE: `@QuarkusTestResource` is merely a convenient extension of `@WithTestResources` for the use of global test resources

BELOW TO EDIT: +
I don't know the behaviour when different scopes are mixed 🤷‍♂️Example:
```java
@WithTestResources(value = TestResourceA.class, scope = TestResourceScope.MATCHING_RESOURCES)
@WithTestResources(value = TestResourceB.class, scope = TestResourceScope.RESTRICTED_TO_CLASS)
@WithTestResources(value = TestResourceC.class, scope = TestResourceScope.GLOBAL)
class TestClass(){}
```
Also maybe add a use case example for why this annotation got introduced and what for the different scopes are useful, as we currently only use GLOBAL because of time reason.
- `TestResourceScope.MATCHING_RESOURCES` (default): Quarkus will group tests with the same test resources and run them together. After a group has been executed, all test resources will be stopped, and the next group will be executed.
- `TestResourceScope.RESTRICTED_TO_CLASS`: The test resource is available only for the annotated test class and will be stopped after the test class has been executed.
- `TestResourceScope.GLOBAL`: Test resources apply to all tests in the testsuite

Quarkus needs to restart if one of the following is true:

- At least one the existing test resources is restricted to the test class
- At least one the next test resources is restricted to the test class
- Different {@code MATCHING_RESOURCE} scoped test resources are being used

== Hang Detection

Expand Down
14 changes: 10 additions & 4 deletions docs/src/main/asciidoc/hibernate-orm.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1159,27 +1159,33 @@ From the implementation above, tenants are resolved from the request path so tha

[NOTE]
====
If you also use xref:security-openid-connect-multitenancy.adoc[OIDC multitenancy] and both OIDC and Hibernate ORM tenant IDs are the same and must be extracted from the Vert.x `RoutingContext` then you can pass the tenant id from the OIDC Tenant Resolver to the Hibernate ORM Tenant Resolver as a `RoutingContext` attribute, for example:
If you also use xref:security-openid-connect-multitenancy.adoc[OIDC multitenancy] and both OIDC and Hibernate ORM tenant IDs are the same,
you can get the OIDC tenant id from a `RoutingContext` attribute like in the example below:

[source,java]
----
import io.quarkus.hibernate.orm.runtime.tenant.TenantResolver;
import io.quarkus.oidc.runtime.OidcUtils;
import io.vertx.ext.web.RoutingContext;

@PersistenceUnitExtension
@RequestScoped
public class CustomTenantResolver implements TenantResolver {

@Inject
RoutingContext context;
RoutingContext context; <1>
...
@Override
public String resolveTenantId() {
// OIDC TenantResolver has already calculated the tenant id and saved it as a RoutingContext `tenantId` attribute:
return context.get("tenantId");
// OIDC has saved the tenant id as the RoutingContext attribute:
return context.get(OidcUtils.TENANT_ID_ATTRIBUTE);
}
}
----
<1> If the Hibernate `TenantResolver` also resolves tenants when there is no active HTTP request,
for example when you query database from a scheduler, the `RoutingContext` CDI bean will not be available.
Please inject the `io.quarkus.vertx.http.runtime.CurrentVertxRequest` CDI bean instead and get the `RoutingContext` from this bean.

====

=== Configuring the application
Expand Down
8 changes: 4 additions & 4 deletions docs/src/main/asciidoc/mongodb-panache.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1275,12 +1275,12 @@ and then `quarkus.mongodb.database` property.
[NOTE]
====
If you also use xref:security-openid-connect-multitenancy.adoc[OIDC multitenancy], then if the OIDC tenantID and MongoDB
database are the same and must be extracted from the Vert.x `RoutingContext` you can pass the tenant id from the OIDC `TenantResolver`
to the MongoDB with Panache `MongoDatabaseResolver` as a `RoutingContext` attribute, for example:
database are the same, you can access the OIDC tenant id from a `RoutingContext` attribute like in the example below:

[source,java]
----
import io.quarkus.mongodb.panache.common.MongoDatabaseResolver;
import io.quarkus.oidc.runtime.OidcUtils;
import io.vertx.ext.web.RoutingContext;

@RequestScoped
Expand All @@ -1291,8 +1291,8 @@ public class CustomMongoDatabaseResolver implements MongoDatabaseResolver {
...
@Override
public String resolve() {
// OIDC TenantResolver has already calculated the tenant id and saved it as a RoutingContext `tenantId` attribute:
return context.get("tenantId");
// OIDC has saved the tenant id as the RoutingContext attribute:
return context.get(OidcUtils.TENANT_ID_ATTRIBUTE);
}
}
----
Expand Down
15 changes: 14 additions & 1 deletion docs/src/main/asciidoc/qute-reference.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,8 @@ First two elements: {#each myArray.take(2)}{it}{/each} <5>

==== Character Escapes

For HTML and XML templates the `'`, `"`, `<`, `>`, `&` characters are escaped by default if a template variant is set.
For HTML and XML templates the `'`, `"`, `<`, `>`, `&` characters are escaped by default if a corresponding template variant is set.
For JSON templates the `"`, `\` and the control characters (`U+0000` through `U+001F`) are escaped by default if a corresponding template variant is set.

NOTE: In Quarkus, a variant is set automatically for templates located in the `src/main/resources/templates`. By default, the `java.net.URLConnection#getFileNameMap()` is used to determine the content-type of a template file. The additional map of suffixes to content types can be set via `quarkus.qute.content-types`.

Expand All @@ -466,6 +467,7 @@ If you need to render the unescaped value:
1. Either use the `raw` or `safe` properties implemented as extension methods of the `java.lang.Object`,
2. Or wrap the `String` value in a `io.quarkus.qute.RawString`.

.HTML Example
[source,html]
----
<html>
Expand All @@ -478,6 +480,17 @@ If you need to render the unescaped value:

TIP: By default, a template with one of the following content types is escaped: `text/html`, `text/xml`, `application/xml` and `application/xhtml+xml`. However, it's possible to extend this list via the `quarkus.qute.escape-content-types` configuration property.

.JSON Example
[source,json]
----
{
"id": "{valueId.raw}", <1>
"name": "{valueName}" <2>
}
----
<1> `valueId` that resolves to `\nA12345` will be rendered as `\nA12345` that will result in an invalid JSON Object because of the new line inserted inside the string value for the attribute `id`.
<2> `valueName` that resolves to `\tExpressions \n Escapes` will be rendered as `\\tExpressions \\n Escapes`.

[[virtual_methods]]
==== Virtual Methods

Expand Down
20 changes: 4 additions & 16 deletions docs/src/main/asciidoc/security-openid-connect-multitenancy.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -329,22 +329,10 @@ A similar technique can be used with `TenantConfigResolver`, where a `tenant-id`

[NOTE]
====
If you also use xref:hibernate-orm.adoc#multitenancy[Hibernate ORM multitenancy] or xref:mongodb-panache.adoc#multitenancy[MongoDB with Panache multitenancy] and both tenant ids are the same
and must be extracted from the Vert.x `RoutingContext`, you can pass the tenant id from the OIDC Tenant Resolver to the Hibernate ORM Tenant Resolver or MongoDB with Panache Mongo Database Resolver
as a `RoutingContext` attribute, for example:

[source,java]
----
public class CustomTenantResolver implements TenantResolver {

@Override
public String resolve(RoutingContext context) {
String tenantId = extractTenantId(context);
context.put("tenantId", tenantId);
return tenantId;
}
}
----
If you also use Hibernate ORM multitenancy or MongoDB with Panache multitenancy and both tenant ids are the same,
you can get the tenant id from the `RoutingContext` attribute with `tenant-id`. You can find more information here:
* xref:hibernate-orm.adoc#multitenancy[Hibernate ORM multitenancy]
* xref:mongodb-panache.adoc#multitenancy[MongoDB with Panache multitenancy]
====

== Starting and configuring the Keycloak server
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,12 @@ public OidcTenantConfig apply(OidcTenantConfig oidcTenantConfig) {
if (oidcTenantConfig == null) {
throw new OIDCException("Tenant configuration has not been resolved");
}
LOG.debugf("Resolved OIDC tenant id: %s", oidcTenantConfig.tenantId.orElse(OidcUtils.DEFAULT_TENANT_ID));
final String tenantId = oidcTenantConfig.tenantId.orElse(OidcUtils.DEFAULT_TENANT_ID);
LOG.debugf("Resolved OIDC tenant id: %s", tenantId);
context.put(OidcTenantConfig.class.getName(), oidcTenantConfig);
if (context.get(OidcUtils.TENANT_ID_ATTRIBUTE) == null) {
context.put(OidcUtils.TENANT_ID_ATTRIBUTE, tenantId);
}
return oidcTenantConfig;
};
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ public class EscapingTest {
.addAsResource(new StringAsset("{text} {other} {text.raw} {text.safe} {item.foo}"),
"templates/bar.txt")
.addAsResource(new StringAsset("{@java.lang.String text}{text} {text.raw} {text.safe}"),
"templates/validation.html"))
"templates/validation.html")
.addAsResource(new StringAsset("{ \"strVal\":\"{strVal}\", \"intVal\":{intVal} }"),
"templates/val.json"))
.overrideConfigKey("quarkus.qute.content-types.xhtml", "application/xhtml+xml")
.overrideConfigKey("quarkus.qute.suffixes", "qute.html,qute.txt,html,txt,xhtml");

Expand Down Expand Up @@ -58,6 +60,12 @@ public void testEscaper() {
item.data("item", new Item()).render());
}

@Test
public void testJsonEscaper() {
assertEquals("{ \"strVal\":\"\\t Foo \\u000b\", \"intVal\":42 }",
engine.getTemplate("val.json").data("strVal", "\t Foo \u000B").data("intVal", 42).render());
}

@Test
public void testValidation() {
assertEquals("&lt;div&gt; <div> <div>",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import io.quarkus.qute.EvalContext;
import io.quarkus.qute.Expression;
import io.quarkus.qute.HtmlEscaper;
import io.quarkus.qute.JsonEscaper;
import io.quarkus.qute.NamespaceResolver;
import io.quarkus.qute.ParserHook;
import io.quarkus.qute.Qute;
Expand Down Expand Up @@ -157,6 +158,9 @@ public EngineProducer(QuteContext context, QuteConfig config, QuteRuntimeConfig
// Escape some characters for HTML/XML templates
builder.addResultMapper(new HtmlEscaper(List.copyOf(config.escapeContentTypes)));

// Escape some characters for JSON templates
builder.addResultMapper(new JsonEscaper());

// Fallback reflection resolver
builder.addValueResolver(new ReflectionValueResolver());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@
import io.quarkus.rest.client.reactive.jackson.runtime.serialisers.ClientJacksonMessageBodyReader;
import io.quarkus.rest.client.reactive.jackson.runtime.serialisers.ClientJacksonMessageBodyWriter;
import io.quarkus.rest.client.reactive.jackson.runtime.serialisers.JacksonCleanupRestClientClosingTask;
import io.quarkus.resteasy.reactive.jackson.deployment.processor.ResteasyReactiveJacksonProviderDefinedBuildItem;
import io.quarkus.resteasy.reactive.jackson.runtime.serialisers.vertx.VertxJsonArrayBasicMessageBodyReader;
import io.quarkus.resteasy.reactive.jackson.runtime.serialisers.vertx.VertxJsonArrayBasicMessageBodyWriter;
import io.quarkus.resteasy.reactive.jackson.runtime.serialisers.vertx.VertxJsonObjectBasicMessageBodyReader;
import io.quarkus.resteasy.reactive.jackson.runtime.serialisers.vertx.VertxJsonObjectBasicMessageBodyWriter;
import io.quarkus.resteasy.reactive.jackson.common.deployment.processor.ResteasyReactiveJacksonProviderDefinedBuildItem;
import io.quarkus.resteasy.reactive.jackson.common.runtime.serialisers.vertx.VertxJsonArrayBasicMessageBodyReader;
import io.quarkus.resteasy.reactive.jackson.common.runtime.serialisers.vertx.VertxJsonArrayBasicMessageBodyWriter;
import io.quarkus.resteasy.reactive.jackson.common.runtime.serialisers.vertx.VertxJsonObjectBasicMessageBodyReader;
import io.quarkus.resteasy.reactive.jackson.common.runtime.serialisers.vertx.VertxJsonObjectBasicMessageBodyWriter;
import io.quarkus.resteasy.reactive.spi.MessageBodyReaderBuildItem;
import io.quarkus.resteasy.reactive.spi.MessageBodyWriterBuildItem;
import io.quarkus.vertx.deployment.ReinitializeVertxJsonBuildItem;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.quarkus.resteasy.reactive.jackson.deployment.processor;
package io.quarkus.resteasy.reactive.jackson.common.deployment.processor;

import io.quarkus.builder.item.MultiBuildItem;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.quarkus.resteasy.reactive.jackson.runtime.serialisers.vertx;
package io.quarkus.resteasy.reactive.jackson.common.runtime.serialisers.vertx;

import java.io.IOException;
import java.io.InputStream;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.quarkus.resteasy.reactive.jackson.runtime.serialisers.vertx;
package io.quarkus.resteasy.reactive.jackson.common.runtime.serialisers.vertx;

import java.io.IOException;
import java.io.OutputStream;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.quarkus.resteasy.reactive.jackson.runtime.serialisers.vertx;
package io.quarkus.resteasy.reactive.jackson.common.runtime.serialisers.vertx;

import java.io.IOException;
import java.io.InputStream;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.quarkus.resteasy.reactive.jackson.runtime.serialisers.vertx;
package io.quarkus.resteasy.reactive.jackson.common.runtime.serialisers.vertx;

import java.io.IOException;
import java.io.OutputStream;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
import io.quarkus.resteasy.reactive.jackson.DisableSecureSerialization;
import io.quarkus.resteasy.reactive.jackson.EnableSecureSerialization;
import io.quarkus.resteasy.reactive.jackson.SecureField;
import io.quarkus.resteasy.reactive.jackson.common.deployment.processor.ResteasyReactiveJacksonProviderDefinedBuildItem;
import io.quarkus.resteasy.reactive.jackson.runtime.ResteasyReactiveServerJacksonRecorder;
import io.quarkus.resteasy.reactive.jackson.runtime.mappers.NativeInvalidDefinitionExceptionMapper;
import io.quarkus.resteasy.reactive.jackson.runtime.security.RolesAllowedConfigExpStorage;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.jboss.resteasy.reactive.server.spi.ServerMessageBodyReader;
import org.jboss.resteasy.reactive.server.spi.ServerRequestContext;

import io.quarkus.resteasy.reactive.jackson.common.runtime.serialisers.vertx.VertxJsonArrayBasicMessageBodyReader;
import io.vertx.core.json.JsonArray;

public class VertxJsonArrayMessageBodyReader extends VertxJsonArrayBasicMessageBodyReader
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.jboss.resteasy.reactive.server.spi.ServerMessageBodyWriter;
import org.jboss.resteasy.reactive.server.spi.ServerRequestContext;

import io.quarkus.resteasy.reactive.jackson.common.runtime.serialisers.vertx.VertxJsonArrayBasicMessageBodyWriter;
import io.vertx.core.json.JsonArray;

public class VertxJsonArrayMessageBodyWriter extends VertxJsonArrayBasicMessageBodyWriter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.jboss.resteasy.reactive.server.spi.ServerMessageBodyReader;
import org.jboss.resteasy.reactive.server.spi.ServerRequestContext;

import io.quarkus.resteasy.reactive.jackson.common.runtime.serialisers.vertx.VertxJsonObjectBasicMessageBodyReader;
import io.vertx.core.json.JsonObject;

public class VertxJsonObjectMessageBodyReader extends VertxJsonObjectBasicMessageBodyReader
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.jboss.resteasy.reactive.server.spi.ServerMessageBodyWriter;
import org.jboss.resteasy.reactive.server.spi.ServerRequestContext;

import io.quarkus.resteasy.reactive.jackson.common.runtime.serialisers.vertx.VertxJsonObjectBasicMessageBodyWriter;
import io.vertx.core.json.JsonObject;

public class VertxJsonObjectMessageBodyWriter extends VertxJsonObjectBasicMessageBodyWriter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,8 @@ private ResultHandle getResponseContentType(MethodCreator methodCreator, List<St
.toArray(ResultHandle[]::new);

String responseContentTypeResolverClassName = isResteasyClassic
? "io.quarkus.spring.web.runtime.ResteasyClassicResponseContentTypeResolver"
: "io.quarkus.spring.web.runtime.ResteasyReactiveResponseContentTypeResolver";
? "io.quarkus.spring.web.resteasy.classic.runtime.ResteasyClassicResponseContentTypeResolver"
: "io.quarkus.spring.web.resteasy.reactive.runtime.ResteasyReactiveResponseContentTypeResolver";
ResultHandle contentTypeResolver = methodCreator
.newInstance(MethodDescriptor.ofConstructor(responseContentTypeResolverClassName));

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.quarkus.spring.web.deployment;
package io.quarkus.spring.web.resteasy.classic.deployment;

import java.io.IOException;
import java.util.ArrayList;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.quarkus.spring.web.runtime;
package io.quarkus.spring.web.resteasy.classic.runtime;

import java.util.List;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.quarkus.spring.web.test;
package io.quarkus.spring.web.resteasy.classic.test;

import static io.restassured.RestAssured.when;
import static org.hamcrest.Matchers.is;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.quarkus.spring.web.test;
package io.quarkus.spring.web.resteasy.classic.test;

import static org.assertj.core.api.Assertions.assertThat;

Expand All @@ -24,7 +24,8 @@ public class MissingRestControllerTest {
.setApplicationName("missing-rest-controller")
.setApplicationVersion("0.1-SNAPSHOT")
.setLogRecordPredicate(
r -> "io.quarkus.spring.web.deployment.SpringWebResteasyClassicProcessor".equals(r.getLoggerName()));
r -> "io.quarkus.spring.web.resteasy.classic.deployment.SpringWebResteasyClassicProcessor"
.equals(r.getLoggerName()));

@ProdBuildResults
private ProdModeTestResults prodModeTestResults;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.quarkus.spring.web.test;
package io.quarkus.spring.web.resteasy.classic.test;

import static io.restassured.RestAssured.when;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.quarkus.spring.web.test;
package io.quarkus.spring.web.resteasy.classic.test;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.quarkus.spring.web.test;
package io.quarkus.spring.web.resteasy.classic.test;

import static io.restassured.RestAssured.when;
import static org.hamcrest.Matchers.is;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.quarkus.spring.web.deployment;
package io.quarkus.spring.web.resteasy.reactive.deployment;

import static org.jboss.jandex.AnnotationInstance.create;
import static org.jboss.resteasy.reactive.common.processor.ResteasyReactiveDotNames.DEFAULT_VALUE;
Expand Down Expand Up @@ -45,8 +45,8 @@
import io.quarkus.resteasy.reactive.spi.AdditionalResourceClassBuildItem;
import io.quarkus.resteasy.reactive.spi.ExceptionMapperBuildItem;
import io.quarkus.resteasy.server.common.spi.AdditionalJaxRsResourceMethodParamAnnotations;
import io.quarkus.spring.web.runtime.ResponseEntityHandler;
import io.quarkus.spring.web.runtime.ResponseStatusHandler;
import io.quarkus.spring.web.resteasy.reactive.runtime.ResponseEntityHandler;
import io.quarkus.spring.web.resteasy.reactive.runtime.ResponseStatusHandler;
import io.quarkus.spring.web.runtime.common.ResponseStatusExceptionMapper;

public class SpringWebResteasyReactiveProcessor {
Expand Down
Loading
Loading