persistenceUnitNames = peristenceUnitBuildItems.stream()
+ .map(HibernateSearchElasticsearchPersistenceUnitConfiguredBuildItem::getPersistenceUnitName)
+ .collect(Collectors.toSet());
+ return new DevConsoleRuntimeTemplateInfoBuildItem("indexedPersistenceUnits",
+ recorder.infoSupplier(runtimeConfig, persistenceUnitNames), this.getClass(), curateOutcomeBuildItem);
}
@BuildStep
diff --git a/extensions/hibernate-search-orm-elasticsearch/deployment/src/main/resources/dev-templates/embedded.html b/extensions/hibernate-search-orm-elasticsearch/deployment/src/main/resources/dev-templates/embedded.html
index 10c92d629e123c..9cc1a072f0350a 100644
--- a/extensions/hibernate-search-orm-elasticsearch/deployment/src/main/resources/dev-templates/embedded.html
+++ b/extensions/hibernate-search-orm-elasticsearch/deployment/src/main/resources/dev-templates/embedded.html
@@ -1,4 +1,7 @@
+
+
+ Persistence units {info:indexedPersistenceUnits.persistenceUnits.size}
- Indexed entity types {info:indexedEntityTypes.size()}
+ Indexed Entities {info:indexedPersistenceUnits.numberOfIndexedEntities}
diff --git a/extensions/hibernate-search-orm-elasticsearch/deployment/src/main/resources/dev-templates/entity-types.html b/extensions/hibernate-search-orm-elasticsearch/deployment/src/main/resources/dev-templates/entity-types.html
index 079f27d7783c20..fd6cdcbffbff00 100644
--- a/extensions/hibernate-search-orm-elasticsearch/deployment/src/main/resources/dev-templates/entity-types.html
+++ b/extensions/hibernate-search-orm-elasticsearch/deployment/src/main/resources/dev-templates/entity-types.html
@@ -1,11 +1,14 @@
{#include main}
{#title}Indexed Entities{/title}
{#body}
-{#if info:indexedEntityTypes.isEmpty}
+{#if info:indexedPersistenceUnits.persistenceUnits.isEmpty}
No indexed entities were found.
{#else}
{/if}
{/body}
diff --git a/extensions/hibernate-search-orm-elasticsearch/runtime/pom.xml b/extensions/hibernate-search-orm-elasticsearch/runtime/pom.xml
index 1f48eef3c9b0b1..e166cddc4de248 100644
--- a/extensions/hibernate-search-orm-elasticsearch/runtime/pom.xml
+++ b/extensions/hibernate-search-orm-elasticsearch/runtime/pom.xml
@@ -38,6 +38,14 @@
javax.persistence
javax.persistence-api
+
+
+ jakarta.activation
+ jakarta.activation-api
+
diff --git a/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/devconsole/HibernateSearchDevConsoleRecorder.java b/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/devconsole/HibernateSearchDevConsoleRecorder.java
index 1a7d66cd2554b1..deff448a12de34 100644
--- a/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/devconsole/HibernateSearchDevConsoleRecorder.java
+++ b/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/devconsole/HibernateSearchDevConsoleRecorder.java
@@ -2,6 +2,8 @@
import java.time.Duration;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Collectors;
@@ -19,9 +21,9 @@
@Recorder
public class HibernateSearchDevConsoleRecorder {
- public Supplier> infoSupplier(
- HibernateSearchElasticsearchRuntimeConfig runtimeConfig) {
- return new HibernateSearchSupplier(runtimeConfig);
+ public Supplier infoSupplier(
+ HibernateSearchElasticsearchRuntimeConfig runtimeConfig, Set persistenceUnitNames) {
+ return new HibernateSearchSupplier(runtimeConfig, persistenceUnitNames);
}
public Handler indexEntity() {
@@ -31,19 +33,25 @@ protected void handlePostAsync(RoutingContext event, MultiMap form) throws Excep
if (form.isEmpty()) {
return;
}
- SearchMapping mapping = HibernateSearchSupplier.searchMapping();
- if (mapping == null) {
+ Set persitenceUnitNames = form.entries().stream().map(Map.Entry::getValue)
+ .collect(Collectors.toSet());
+ Map mappings = HibernateSearchSupplier.searchMapping(persitenceUnitNames);
+ if (mappings.isEmpty()) {
flashMessage(event, "There are no indexed entity types.", FlashScopeUtil.FlashMessageStatus.ERROR);
return;
}
- mapping.scope(Object.class,
- mapping.allIndexedEntities().stream()
- .map(SearchIndexedEntity::jpaName)
- .filter(form::contains)
- .collect(Collectors.toList()))
- .massIndexer()
- .startAndWait();
- flashMessage(event, "Entities successfully reindexed", Duration.ofSeconds(10));
+ for (Map.Entry entry : mappings.entrySet()) {
+ SearchMapping mapping = entry.getValue();
+ List entityNames = mapping.allIndexedEntities().stream()
+ .map(SearchIndexedEntity::jpaName)
+ .filter(jpaName -> form.contains(jpaName, entry.getKey(), false))
+ .collect(Collectors.toList());
+ if (!entityNames.isEmpty()) {
+ mapping.scope(Object.class, entityNames).massIndexer()
+ .startAndWait();
+ flashMessage(event, "Entities successfully reindexed", Duration.ofSeconds(10));
+ }
+ }
}
};
}
diff --git a/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/devconsole/HibernateSearchSupplier.java b/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/devconsole/HibernateSearchSupplier.java
index 2460e905887c68..ef2b8422636925 100644
--- a/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/devconsole/HibernateSearchSupplier.java
+++ b/extensions/hibernate-search-orm-elasticsearch/runtime/src/main/java/io/quarkus/hibernate/search/orm/elasticsearch/runtime/devconsole/HibernateSearchSupplier.java
@@ -1,44 +1,125 @@
package io.quarkus.hibernate.search.orm.elasticsearch.runtime.devconsole;
-import java.util.Collections;
+import java.lang.annotation.Annotation;
+import java.util.Arrays;
+import java.util.Comparator;
import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
import java.util.function.Supplier;
+import java.util.stream.Collector;
import java.util.stream.Collectors;
+import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.search.mapper.orm.entity.SearchIndexedEntity;
import org.hibernate.search.mapper.orm.mapping.SearchMapping;
import io.quarkus.arc.Arc;
+import io.quarkus.hibernate.orm.PersistenceUnit;
+import io.quarkus.hibernate.orm.runtime.PersistenceUnitUtil;
import io.quarkus.hibernate.search.orm.elasticsearch.runtime.HibernateSearchElasticsearchRuntimeConfig;
-import io.quarkus.hibernate.search.orm.elasticsearch.runtime.devconsole.HibernateSearchSupplier.DevUiIndexedEntity;
-public class HibernateSearchSupplier implements Supplier> {
+public class HibernateSearchSupplier implements Supplier {
private final HibernateSearchElasticsearchRuntimeConfig runtimeConfig;
+ private final Set persistenceUnitNames;
- HibernateSearchSupplier(HibernateSearchElasticsearchRuntimeConfig runtimeConfig) {
+ HibernateSearchSupplier(HibernateSearchElasticsearchRuntimeConfig runtimeConfig, Set persistenceUnitNames) {
this.runtimeConfig = runtimeConfig;
+ this.persistenceUnitNames = persistenceUnitNames;
}
@Override
- public List get() {
+ public IndexedPersistenceUnits get() {
if (!isEnabled()) {
- return Collections.emptyList();
+ return new IndexedPersistenceUnits();
}
- SearchMapping mapping = searchMapping();
- if (mapping == null) {
- return Collections.emptyList();
+ Map mappings = searchMapping(persistenceUnitNames);
+ if (mappings.isEmpty()) {
+ return new IndexedPersistenceUnits();
}
- return mapping.allIndexedEntities().stream().map(DevUiIndexedEntity::new).sorted()
- .collect(Collectors.toList());
+ return mappings.entrySet().stream()
+ .map(mapping -> new IndexedPersistenceUnit(mapping.getKey(),
+ mapping.getValue().allIndexedEntities().stream().map(DevUiIndexedEntity::new).sorted()
+ .collect(Collectors.toList())))
+ .collect(Collector.of(IndexedPersistenceUnits::new, IndexedPersistenceUnits::add,
+ (left, right) -> {
+ left.addAll(right);
+ return left;
+ }));
}
private boolean isEnabled() {
return runtimeConfig.defaultPersistenceUnit.enabled;
}
- public static SearchMapping searchMapping() {
- return Arc.container().instance(SearchMapping.class).get();
+ public static Map searchMapping(Set persistenceUnitNames) {
+ return Arrays.stream(getPersistenceUnitQualifiers(persistenceUnitNames)).map(
+ qualifier -> Arc.container().select(SearchMapping.class, qualifier).get())
+ .collect(Collectors.toMap(HibernateSearchSupplier::getPersistenceUnitName, mapping -> mapping));
+ }
+
+ private static Annotation[] getPersistenceUnitQualifiers(Set persistenceUnitNames) {
+ return persistenceUnitNames.stream().map(PersistenceUnit.PersistenceUnitLiteral::new).toArray(Annotation[]::new);
+ }
+
+ private static String getPersistenceUnitName(SearchMapping searchMapping) {
+ SessionFactoryImplementor sessionFactory = searchMapping.toOrmSessionFactory().unwrap(SessionFactoryImplementor.class);
+ String name = sessionFactory.getName();
+ if (name != null) {
+ return name;
+ }
+ Object persistenceUnitName = sessionFactory.getProperties().get("hibernate.ejb.persistenceUnitName");
+ if (persistenceUnitName != null) {
+ return persistenceUnitName.toString();
+ }
+ return PersistenceUnitUtil.DEFAULT_PERSISTENCE_UNIT_NAME;
+ }
+
+ static class IndexedPersistenceUnits {
+ private final Set persistenceUnits = new TreeSet<>(new PersistenceUnitComparator());
+
+ public Set getPersistenceUnits() {
+ return persistenceUnits;
+ }
+
+ public void add(IndexedPersistenceUnit indexedPersistenceUnit) {
+ persistenceUnits.add(indexedPersistenceUnit);
+ }
+
+ public void addAll(IndexedPersistenceUnits right) {
+ persistenceUnits.addAll(right.persistenceUnits);
+ }
+
+ public int getNumberOfIndexedEntities() {
+ return persistenceUnits.stream().mapToInt(pu -> pu.indexedEntities.size()).sum();
+ }
+ }
+
+ static class PersistenceUnitComparator implements Comparator {
+ Comparator persistenceUnitNameComparator = new PersistenceUnitUtil.PersistenceUnitNameComparator();
+
+ @Override
+ public int compare(IndexedPersistenceUnit o1, IndexedPersistenceUnit o2) {
+ return persistenceUnitNameComparator.compare(o1.persistenceUnitName, o2.persistenceUnitName);
+ }
+ }
+
+ static class IndexedPersistenceUnit implements Comparable {
+ public final String persistenceUnitName;
+
+ public final List indexedEntities;
+
+ public IndexedPersistenceUnit(String persistenceUnitName, List indexedEntities) {
+ this.persistenceUnitName = persistenceUnitName;
+ this.indexedEntities = indexedEntities;
+ }
+
+ @Override
+ public int compareTo(IndexedPersistenceUnit o) {
+ return this.persistenceUnitName.compareTo(o.persistenceUnitName);
+ }
}
public static class DevUiIndexedEntity implements Comparable {
diff --git a/extensions/opentelemetry/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/OpenTelemetryMDCTest.java b/extensions/opentelemetry/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/OpenTelemetryMDCTest.java
new file mode 100644
index 00000000000000..30b114d42cacd6
--- /dev/null
+++ b/extensions/opentelemetry/opentelemetry/deployment/src/test/java/io/quarkus/opentelemetry/deployment/OpenTelemetryMDCTest.java
@@ -0,0 +1,187 @@
+package io.quarkus.opentelemetry.deployment;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+
+import org.jboss.logging.MDC;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import io.opentelemetry.api.trace.Span;
+import io.opentelemetry.api.trace.Tracer;
+import io.opentelemetry.context.Scope;
+import io.opentelemetry.sdk.trace.data.SpanData;
+import io.quarkus.arc.Unremovable;
+import io.quarkus.test.QuarkusUnitTest;
+import io.restassured.RestAssured;
+
+public class OpenTelemetryMDCTest {
+ @RegisterExtension
+ static final QuarkusUnitTest unitTest = new QuarkusUnitTest()
+ .withApplicationRoot((jar) -> jar
+ .addClass(MdcEntry.class)
+ .addClass(TestMdcCapturer.class)
+ .addClass(TestSpanExporter.class)
+ .addClass(TestResource.class));
+
+ @Inject
+ TestSpanExporter spanExporter;
+ @Inject
+ TestMdcCapturer testMdcCapturer;
+ @Inject
+ Tracer tracer;
+
+ @AfterEach
+ void tearDown() {
+ spanExporter.reset();
+ testMdcCapturer.reset();
+ }
+
+ @Test
+ void vertx() {
+ RestAssured.when()
+ .get("/hello").then()
+ .statusCode(200)
+ .body(is("hello"));
+
+ List spans = spanExporter.getFinishedSpanItems(2);
+
+ List mdcEntries = testMdcCapturer.getCapturedMdcEntries();
+
+ List expectedMdcEntries = getExpectedMDCEntries(spans);
+
+ assertEquals("something", spans.get(0).getName());
+ assertEquals("/hello", spans.get(1).getName());
+ assertEquals(expectedMdcEntries, mdcEntries);
+ }
+
+ @Test
+ void nonVertx() {
+ Span parentSpan = tracer.spanBuilder("parent").startSpan();
+ try (Scope ignored = parentSpan.makeCurrent()) {
+ testMdcCapturer.captureMdc();
+ Span childSpan = tracer.spanBuilder("child").startSpan();
+ try (Scope ignored1 = childSpan.makeCurrent()) {
+ testMdcCapturer.captureMdc();
+ } finally {
+ childSpan.end();
+ }
+ } finally {
+ parentSpan.end();
+ }
+
+ List spans = spanExporter.getFinishedSpanItems(2);
+
+ List mdcEntries = testMdcCapturer.getCapturedMdcEntries();
+
+ List expectedMdcEntries = getExpectedMDCEntries(spans);
+
+ assertEquals("child", spans.get(0).getName());
+ assertEquals("parent", spans.get(1).getName());
+ assertEquals(expectedMdcEntries, mdcEntries);
+ }
+
+ private List getExpectedMDCEntries(List spans) {
+ return spans.stream()
+ .map(spanData -> new MdcEntry(spanData.getSpanContext().isSampled(),
+ spanData.getParentSpanContext().isValid() ? spanData.getParentSpanId() : "null",
+ spanData.getSpanId(),
+ spanData.getTraceId()))
+ .collect(Collectors.collectingAndThen(Collectors.toList(), l -> {
+ Collections.reverse(l);
+ return l;
+ }));
+ }
+
+ @ApplicationScoped
+ @Path("/")
+ public static class TestResource {
+
+ @Inject
+ TestMdcCapturer testMdcCapturer;
+
+ @Inject
+ Tracer tracer;
+
+ @GET
+ @Path("/hello")
+ public String hello() {
+ testMdcCapturer.captureMdc();
+ Span span = tracer.spanBuilder("something").startSpan();
+ try (Scope ignored = span.makeCurrent()) {
+ testMdcCapturer.captureMdc();
+ } finally {
+ span.end();
+ }
+ return "hello";
+ }
+ }
+
+ @Unremovable
+ @ApplicationScoped
+ public static class TestMdcCapturer {
+ private final List mdcEntries = Collections.synchronizedList(new ArrayList<>());
+
+ public void reset() {
+ mdcEntries.clear();
+ }
+
+ public void captureMdc() {
+ mdcEntries.add(new MdcEntry(
+ Boolean.parseBoolean(String.valueOf(MDC.get("sampled"))),
+ String.valueOf(MDC.get("parentId")),
+ String.valueOf(MDC.get("spanId")),
+ String.valueOf(MDC.get("traceId"))));
+ }
+
+ public List getCapturedMdcEntries() {
+ return List.copyOf(mdcEntries);
+ }
+ }
+
+ public static class MdcEntry {
+ public final boolean isSampled;
+ public final String parentId;
+ public final String spanId;
+ public final String traceId;
+
+ public MdcEntry(boolean isSampled, String parentId, String spanId, String traceId) {
+ this.isSampled = isSampled;
+ this.parentId = parentId;
+ this.spanId = spanId;
+ this.traceId = traceId;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (!(o instanceof MdcEntry)) {
+ return false;
+ }
+ MdcEntry mdcEntry = (MdcEntry) o;
+ return isSampled == mdcEntry.isSampled &&
+ Objects.equals(parentId, mdcEntry.parentId) &&
+ Objects.equals(spanId, mdcEntry.spanId) &&
+ Objects.equals(traceId, mdcEntry.traceId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(isSampled, parentId, spanId, traceId);
+ }
+ }
+}
diff --git a/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/MDCEnabledContextStorage.java b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/MDCEnabledContextStorage.java
new file mode 100644
index 00000000000000..c3d357e24fc6d2
--- /dev/null
+++ b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/MDCEnabledContextStorage.java
@@ -0,0 +1,38 @@
+package io.quarkus.opentelemetry.runtime;
+
+import io.opentelemetry.context.Context;
+import io.opentelemetry.context.ContextStorage;
+import io.opentelemetry.context.Scope;
+
+/**
+ * A Context Storage that wraps the default OpenTelemetry ContextStorage and
+ * adds MDC functionality.
+ */
+enum MDCEnabledContextStorage implements ContextStorage {
+ INSTANCE;
+
+ private static final ContextStorage DEFAULT_CONTEXT_STORAGE = ContextStorage.defaultStorage();
+
+ @Override
+ public Scope attach(Context toAttach) {
+ Context beforeAttach = current();
+
+ OpenTelemetryUtil.setMDCData(toAttach, null);
+
+ Scope scope = DEFAULT_CONTEXT_STORAGE.attach(toAttach);
+
+ return () -> {
+ if (beforeAttach == null) {
+ OpenTelemetryUtil.clearMDCData(null);
+ } else {
+ OpenTelemetryUtil.setMDCData(beforeAttach, null);
+ }
+ scope.close();
+ };
+ }
+
+ @Override
+ public Context current() {
+ return DEFAULT_CONTEXT_STORAGE.current();
+ }
+}
diff --git a/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/OpenTelemetryUtil.java b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/OpenTelemetryUtil.java
index a4eb7b180f8e4b..c406794ba449d6 100644
--- a/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/OpenTelemetryUtil.java
+++ b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/OpenTelemetryUtil.java
@@ -11,12 +11,22 @@
import java.util.stream.StreamSupport;
import io.opentelemetry.api.baggage.propagation.W3CBaggagePropagator;
+import io.opentelemetry.api.trace.Span;
+import io.opentelemetry.api.trace.SpanContext;
import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator;
+import io.opentelemetry.context.Context;
import io.opentelemetry.context.propagation.ContextPropagators;
import io.opentelemetry.context.propagation.TextMapPropagator;
import io.opentelemetry.sdk.autoconfigure.spi.ConfigurablePropagatorProvider;
+import io.opentelemetry.sdk.trace.ReadableSpan;
+import io.quarkus.vertx.core.runtime.VertxMDC;
public final class OpenTelemetryUtil {
+ public static final String TRACE_ID = "traceId";
+ public static final String SPAN_ID = "spanId";
+ public static final String SAMPLED = "sampled";
+ public static final String PARENT_ID = "parentId";
+
private OpenTelemetryUtil() {
}
@@ -74,4 +84,42 @@ public static Map convertKeyValueListToMap(List headers)
.map(keyValuePair -> new AbstractMap.SimpleImmutableEntry<>(keyValuePair[0].trim(), keyValuePair[1].trim()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (first, next) -> next, LinkedHashMap::new));
}
+
+ /**
+ * Sets MDC data by using the current span from the context.
+ *
+ * @param context opentelemetry context
+ * @param vertxContext vertx context
+ */
+ public static void setMDCData(Context context, io.vertx.core.Context vertxContext) {
+ Span span = Span.fromContextOrNull(context);
+ if (span != null) {
+ SpanContext spanContext = span.getSpanContext();
+ VertxMDC vertxMDC = VertxMDC.INSTANCE;
+ vertxMDC.put(SPAN_ID, spanContext.getSpanId(), vertxContext);
+ vertxMDC.put(TRACE_ID, spanContext.getTraceId(), vertxContext);
+ vertxMDC.put(SAMPLED, Boolean.toString(spanContext.isSampled()), vertxContext);
+ if (span instanceof ReadableSpan) {
+ SpanContext parentSpanContext = ((ReadableSpan) span).getParentSpanContext();
+ if (parentSpanContext.isValid()) {
+ vertxMDC.put(PARENT_ID, parentSpanContext.getSpanId(), vertxContext);
+ } else {
+ vertxMDC.remove(PARENT_ID, vertxContext);
+ }
+ }
+ }
+ }
+
+ /**
+ * Clears MDC data related to OpenTelemetry
+ *
+ * @param vertxContext vertx context
+ */
+ public static void clearMDCData(io.vertx.core.Context vertxContext) {
+ VertxMDC vertxMDC = VertxMDC.INSTANCE;
+ vertxMDC.remove(TRACE_ID, vertxContext);
+ vertxMDC.remove(SPAN_ID, vertxContext);
+ vertxMDC.remove(PARENT_ID, vertxContext);
+ vertxMDC.remove(SAMPLED, vertxContext);
+ }
}
diff --git a/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/QuarkusContextStorage.java b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/QuarkusContextStorage.java
index fb8b1d0ad1adb9..7452f6dcfcf8a0 100644
--- a/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/QuarkusContextStorage.java
+++ b/extensions/opentelemetry/opentelemetry/runtime/src/main/java/io/quarkus/opentelemetry/runtime/QuarkusContextStorage.java
@@ -14,7 +14,8 @@
/**
* Bridges the OpenTelemetry ContextStorage with the Vert.x Context. The default OpenTelemetry ContextStorage (based in
* ThreadLocals) is not suitable for Vert.x. In this case, the OpenTelemetry Context piggybacks on top of the Vert.x
- * Context. If the Vert.x Context is not available, fallbacks to the default OpenTelemetry ContextStorage.
+ * Context. If the Vert.x Context is not available, fallbacks to an MDC enabled context storage that wraps the default
+ * OpenTelemetry ContextStorage.
*/
public enum QuarkusContextStorage implements ContextStorage {
INSTANCE;
@@ -22,7 +23,7 @@ public enum QuarkusContextStorage implements ContextStorage {
private static final Logger log = Logger.getLogger(QuarkusContextStorage.class);
private static final String OTEL_CONTEXT = QuarkusContextStorage.class.getName() + ".otelContext";
- private static final ContextStorage DEFAULT_CONTEXT_STORAGE = ContextStorage.defaultStorage();
+ private static final ContextStorage FALLBACK_CONTEXT_STORAGE = MDCEnabledContextStorage.INSTANCE;
static Vertx vertx;
/**
@@ -37,7 +38,7 @@ public enum QuarkusContextStorage implements ContextStorage {
public Scope attach(Context toAttach) {
io.vertx.core.Context vertxContext = getVertxContext();
return vertxContext != null && isDuplicatedContext(vertxContext) ? attach(vertxContext, toAttach)
- : DEFAULT_CONTEXT_STORAGE.attach(toAttach);
+ : FALLBACK_CONTEXT_STORAGE.attach(toAttach);
}
/**
@@ -64,6 +65,7 @@ public Scope attach(io.vertx.core.Context vertxContext, Context toAttach) {
}
vertxContext.putLocal(OTEL_CONTEXT, toAttach);
+ OpenTelemetryUtil.setMDCData(toAttach, vertxContext);
return () -> {
if (getContext(vertxContext) != toAttach) {
@@ -72,8 +74,10 @@ public Scope attach(io.vertx.core.Context vertxContext, Context toAttach) {
if (beforeAttach == null) {
vertxContext.removeLocal(OTEL_CONTEXT);
+ OpenTelemetryUtil.clearMDCData(vertxContext);
} else {
vertxContext.putLocal(OTEL_CONTEXT, beforeAttach);
+ OpenTelemetryUtil.setMDCData(beforeAttach, vertxContext);
}
};
}
@@ -90,7 +94,7 @@ public Context current() {
if (current != null) {
return current.getLocal(OTEL_CONTEXT);
} else {
- return DEFAULT_CONTEXT_STORAGE.current();
+ return FALLBACK_CONTEXT_STORAGE.current();
}
}
diff --git a/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/resource/basic/MediaTypesWithSuffixHandlingTest.java b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/resource/basic/MediaTypesWithSuffixHandlingTest.java
new file mode 100644
index 00000000000000..4b741ca17e0642
--- /dev/null
+++ b/extensions/resteasy-reactive/quarkus-resteasy-reactive/deployment/src/test/java/io/quarkus/resteasy/reactive/server/test/resource/basic/MediaTypesWithSuffixHandlingTest.java
@@ -0,0 +1,216 @@
+package io.quarkus.resteasy.reactive.server.test.resource.basic;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.nio.charset.StandardCharsets;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.Provider;
+
+import org.hamcrest.Matchers;
+import org.jboss.resteasy.reactive.server.spi.ResteasyReactiveResourceInfo;
+import org.jboss.resteasy.reactive.server.spi.ServerMessageBodyReader;
+import org.jboss.resteasy.reactive.server.spi.ServerMessageBodyWriter;
+import org.jboss.resteasy.reactive.server.spi.ServerRequestContext;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
+
+import io.quarkus.test.QuarkusUnitTest;
+import io.restassured.RestAssured;
+
+public class MediaTypesWithSuffixHandlingTest {
+
+ @RegisterExtension
+ static QuarkusUnitTest testExtension = new QuarkusUnitTest()
+ .setArchiveProducer(() -> {
+ JavaArchive archive = ShrinkWrap.create(JavaArchive.class);
+ archive.addClasses(TestResource.class, NoSuffixMessageBodyWriter.class, SuffixMessageBodyWriter.class);
+ return archive;
+ });
+
+ @Test
+ public void testWriterWithoutSuffix() {
+ RestAssured.get("/test/writer/with-no-suffix")
+ .then()
+ .statusCode(200)
+ .body(Matchers.equalTo("result - no suffix writer"));
+ }
+
+ @Test
+ public void testReaderWithoutSuffix() {
+ RestAssured.get("/test/reader/with-no-suffix")
+ .then()
+ .statusCode(200)
+ .body(Matchers.equalTo("from reader - result"));
+ }
+
+ @Test
+ public void testWriterWithSuffix() {
+ RestAssured.get("/test/writer/with-suffix")
+ .then()
+ .statusCode(200)
+ .body(Matchers.equalTo("result - suffix writer"));
+ }
+
+ @Test
+ public void testReaderWithSuffix() {
+ RestAssured.get("/test/reader/with-suffix")
+ .then()
+ .statusCode(200)
+ .body(Matchers.equalTo("from reader suffix - result"));
+ }
+
+ @Path("/test")
+ public static class TestResource {
+
+ @GET
+ @Path("/writer/with-no-suffix")
+ @Produces("text/test")
+ public String writerSimple() {
+ return "result";
+ }
+
+ @GET
+ @Path("/writer/with-suffix")
+ @Produces("text/test+suffix")
+ public String writerSuffix() {
+ return "result";
+ }
+
+ @GET
+ @Path("/reader/with-no-suffix")
+ @Consumes("text/test")
+ public String readerSimple(Object fromReader) {
+ return fromReader + " - result";
+ }
+
+ @GET
+ @Path("/reader/with-suffix")
+ @Consumes("text/test+suffix")
+ public String readerSuffix(Object fromReader) {
+ return fromReader + " - result";
+ }
+ }
+
+ @Provider
+ @Consumes("text/test")
+ @Produces("text/test")
+ public static class NoSuffixMessageBodyWriter implements ServerMessageBodyWriter, ServerMessageBodyReader {
+
+ @Override
+ public boolean isWriteable(Class> type, Type genericType, ResteasyReactiveResourceInfo target, MediaType mediaType) {
+ return true;
+ }
+
+ @Override
+ public void writeResponse(Object o, Type genericType, ServerRequestContext context)
+ throws WebApplicationException, IOException {
+ String response = (String) o;
+ response += " - no suffix writer";
+ context.getOrCreateOutputStream().write(response.getBytes(StandardCharsets.UTF_8));
+ }
+
+ @Override
+ public boolean isWriteable(Class> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ throw new IllegalStateException("should never have been called");
+ }
+
+ @Override
+ public void writeTo(Object o, Class> type, Type genericType, Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap httpHeaders, OutputStream entityStream)
+ throws IOException, WebApplicationException {
+ throw new IllegalStateException("should never have been called");
+ }
+
+ @Override
+ public boolean isReadable(Class> type, Type genericType, ResteasyReactiveResourceInfo lazyMethod,
+ MediaType mediaType) {
+ return true;
+ }
+
+ @Override
+ public Object readFrom(Class type, Type genericType, MediaType mediaType,
+ ServerRequestContext context) throws WebApplicationException {
+ return "from reader";
+ }
+
+ @Override
+ public boolean isReadable(Class> aClass, Type type, Annotation[] annotations, MediaType mediaType) {
+ throw new IllegalStateException("should never have been called");
+ }
+
+ @Override
+ public Object readFrom(Class aClass, Type type, Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap multivaluedMap, InputStream inputStream)
+ throws WebApplicationException {
+ throw new IllegalStateException("should never have been called");
+ }
+ }
+
+ @Provider
+ @Consumes("text/test+suffix")
+ @Produces("text/test+suffix")
+ public static class SuffixMessageBodyWriter implements ServerMessageBodyWriter, ServerMessageBodyReader {
+
+ @Override
+ public boolean isWriteable(Class> type, Type genericType, ResteasyReactiveResourceInfo target, MediaType mediaType) {
+ return true;
+ }
+
+ @Override
+ public void writeResponse(Object o, Type genericType, ServerRequestContext context)
+ throws WebApplicationException, IOException {
+ String response = (String) o;
+ response += " - suffix writer";
+ context.getOrCreateOutputStream().write(response.getBytes(StandardCharsets.UTF_8));
+ }
+
+ @Override
+ public boolean isWriteable(Class> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ throw new IllegalStateException("should never have been called");
+ }
+
+ @Override
+ public void writeTo(Object o, Class> type, Type genericType, Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap httpHeaders, OutputStream entityStream)
+ throws IOException, WebApplicationException {
+ throw new IllegalStateException("should never have been called");
+ }
+
+ @Override
+ public boolean isReadable(Class> type, Type genericType, ResteasyReactiveResourceInfo lazyMethod,
+ MediaType mediaType) {
+ return true;
+ }
+
+ @Override
+ public Object readFrom(Class type, Type genericType, MediaType mediaType,
+ ServerRequestContext context) throws WebApplicationException {
+ return "from reader suffix";
+ }
+
+ @Override
+ public boolean isReadable(Class> aClass, Type type, Annotation[] annotations, MediaType mediaType) {
+ throw new IllegalStateException("should never have been called");
+ }
+
+ @Override
+ public Object readFrom(Class aClass, Type type, Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap multivaluedMap, InputStream inputStream)
+ throws WebApplicationException {
+ throw new IllegalStateException("should never have been called");
+ }
+ }
+
+}
diff --git a/independent-projects/qute/pom.xml b/independent-projects/qute/pom.xml
index d6917d25cf73a0..ff0459518cc241 100644
--- a/independent-projects/qute/pom.xml
+++ b/independent-projects/qute/pom.xml
@@ -46,7 +46,7 @@
3.5.0.Final
3.0.0-M5
1.6.8
- 1.4.0
+ 1.5.0
diff --git a/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/ClientReaderInterceptorContextImpl.java b/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/ClientReaderInterceptorContextImpl.java
index c73f288f0c87a9..55815186fa9598 100644
--- a/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/ClientReaderInterceptorContextImpl.java
+++ b/independent-projects/resteasy-reactive/client/runtime/src/main/java/org/jboss/resteasy/reactive/client/impl/ClientReaderInterceptorContextImpl.java
@@ -17,7 +17,6 @@
import org.jboss.resteasy.reactive.common.core.Serialisers;
import org.jboss.resteasy.reactive.common.jaxrs.ConfigurationImpl;
import org.jboss.resteasy.reactive.common.util.CaseInsensitiveMap;
-import org.jboss.resteasy.reactive.common.util.MediaTypeHelper;
public class ClientReaderInterceptorContextImpl extends AbstractClientInterceptorContextImpl
implements ReaderInterceptorContext {
@@ -35,7 +34,7 @@ public ClientReaderInterceptorContextImpl(Annotation[] annotations, Class> ent
Map properties, MultivaluedMap headers,
ConfigurationImpl configuration, Serialisers serialisers, InputStream inputStream,
ReaderInterceptor[] interceptors) {
- super(annotations, entityClass, entityType, MediaTypeHelper.withSuffixAsSubtype(mediaType), properties);
+ super(annotations, entityClass, entityType, mediaType, properties);
this.configuration = configuration;
this.serialisers = serialisers;
this.inputStream = inputStream;
diff --git a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/core/Serialisers.java b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/core/Serialisers.java
index 9a1c82d1795ba2..e543e7cf976cb5 100644
--- a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/core/Serialisers.java
+++ b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/core/Serialisers.java
@@ -43,7 +43,7 @@ public List> findReaders(ConfigurationImpl configuration, C
public List> findReaders(ConfigurationImpl configuration, Class> entityType,
MediaType mediaType, RuntimeType runtimeType) {
- List mt = Collections.singletonList(mediaType);
+ List desired = MediaTypeHelper.getUngroupedMediaTypes(mediaType);
List> ret = new ArrayList<>();
Deque> toProcess = new LinkedList<>();
Class> klass = entityType;
@@ -66,7 +66,7 @@ public List> findReaders(ConfigurationImpl configuration, C
while (!toProcess.isEmpty()) {
Class> iface = toProcess.poll();
List goodTypeReaders = readers.get(iface);
- readerLookup(mediaType, runtimeType, mt, ret, goodTypeReaders);
+ readerLookup(mediaType, runtimeType, desired, ret, goodTypeReaders);
for (Class> i : iface.getInterfaces()) {
if (!seen.contains(i)) {
seen.add(i);
@@ -76,7 +76,7 @@ public List> findReaders(ConfigurationImpl configuration, C
}
}
List goodTypeReaders = readers.get(klass);
- readerLookup(mediaType, runtimeType, mt, ret, goodTypeReaders);
+ readerLookup(mediaType, runtimeType, desired, ret, goodTypeReaders);
if (klass.isInterface()) {
klass = Object.class;
} else {
@@ -87,7 +87,8 @@ public List> findReaders(ConfigurationImpl configuration, C
return ret;
}
- private void readerLookup(MediaType mediaType, RuntimeType runtimeType, List mt, List> ret,
+ private void readerLookup(MediaType mediaType, RuntimeType runtimeType, List desired,
+ List> ret,
List goodTypeReaders) {
if (goodTypeReaders != null && !goodTypeReaders.isEmpty()) {
List mediaTypeMatchingReaders = new ArrayList<>(goodTypeReaders.size());
@@ -96,13 +97,15 @@ private void readerLookup(MediaType mediaType, RuntimeType runtimeType, List> findBuildTimeWriters(Class> entityType, Runt
protected List findResourceWriters(QuarkusMultivaluedMap, ResourceWriter> writers, Class> klass,
List produces, RuntimeType runtimeType) {
+ Class> currentClass = klass;
+ List desired = MediaTypeHelper.getUngroupedMediaTypes(produces);
List ret = new ArrayList<>();
Deque> toProcess = new LinkedList<>();
do {
- if (klass == Object.class) {
+ if (currentClass == Object.class) {
//spec extension, look for interfaces as well
//we match interfaces before Object
Set> seen = new HashSet<>(toProcess);
while (!toProcess.isEmpty()) {
Class> iface = toProcess.poll();
List goodTypeWriters = writers.get(iface);
- writerLookup(runtimeType, produces, ret, goodTypeWriters);
+ writerLookup(runtimeType, produces, desired, ret, goodTypeWriters);
for (Class> i : iface.getInterfaces()) {
if (!seen.contains(i)) {
seen.add(i);
@@ -170,15 +175,16 @@ protected List findResourceWriters(QuarkusMultivaluedMap goodTypeWriters = writers.get(klass);
- writerLookup(runtimeType, produces, ret, goodTypeWriters);
- toProcess.addAll(Arrays.asList(klass.getInterfaces()));
+ List goodTypeWriters = writers.get(currentClass);
+ writerLookup(runtimeType, produces, desired, ret, goodTypeWriters);
+ toProcess.addAll(Arrays.asList(currentClass.getInterfaces()));
// if we're an interface, pretend our superclass is Object to get us through the same logic as a class
- if (klass.isInterface())
- klass = Object.class;
- else
- klass = klass.getSuperclass();
- } while (klass != null);
+ if (currentClass.isInterface()) {
+ currentClass = Object.class;
+ } else {
+ currentClass = currentClass.getSuperclass();
+ }
+ } while (currentClass != null);
return ret;
}
@@ -200,22 +206,25 @@ protected List> toMessageBodyWriters(List r
return ret;
}
- private void writerLookup(RuntimeType runtimeType, List mt, List ret,
- List goodTypeWriters) {
+ private void writerLookup(RuntimeType runtimeType, List produces, List desired,
+ List ret, List goodTypeWriters) {
if (goodTypeWriters != null && !goodTypeWriters.isEmpty()) {
List mediaTypeMatchingWriters = new ArrayList<>(goodTypeWriters.size());
+
for (int i = 0; i < goodTypeWriters.size(); i++) {
ResourceWriter goodTypeWriter = goodTypeWriters.get(i);
if (!goodTypeWriter.matchesRuntimeType(runtimeType)) {
continue;
}
- MediaType match = MediaTypeHelper.getFirstMatch(mt, goodTypeWriter.mediaTypes());
+ MediaType match = MediaTypeHelper.getFirstMatch(desired, goodTypeWriter.mediaTypes());
if (match != null) {
mediaTypeMatchingWriters.add(goodTypeWriter);
}
}
+
// we sort here because the spec mentions that the writers closer to the requested java type are tried first
- mediaTypeMatchingWriters.sort(ResourceWriter.ResourceWriterComparator.INSTANCE);
+ mediaTypeMatchingWriters.sort(new ResourceWriter.ResourceWriterComparator(produces));
+
ret.addAll(mediaTypeMatchingWriters);
}
}
diff --git a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/model/ResourceReader.java b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/model/ResourceReader.java
index 69ad09b953e4ae..ca73e22378d915 100644
--- a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/model/ResourceReader.java
+++ b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/model/ResourceReader.java
@@ -114,7 +114,11 @@ public boolean matchesRuntimeType(RuntimeType runtimeType) {
*/
public static class ResourceReaderComparator implements Comparator {
- public static final ResourceReaderComparator INSTANCE = new ResourceReaderComparator();
+ private final List produces;
+
+ public ResourceReaderComparator(List produces) {
+ this.produces = produces;
+ }
@Override
public int compare(ResourceReader o1, ResourceReader o2) {
@@ -144,6 +148,14 @@ public int compare(ResourceReader o1, ResourceReader o2) {
return mediaTypeCompare;
}
+ // try to compare using the number of matching produces media types
+ if (!produces.isEmpty()) {
+ mediaTypeCompare = MediaTypeHelper.compareMatchingMediaTypes(produces, mediaTypes1, mediaTypes2);
+ if (mediaTypeCompare != 0) {
+ return mediaTypeCompare;
+ }
+ }
+
// done to make the sorting result deterministic
return Integer.compare(mediaTypes1.size(), mediaTypes2.size());
}
diff --git a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/model/ResourceWriter.java b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/model/ResourceWriter.java
index d04c4420c801d4..381c363b60667b 100644
--- a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/model/ResourceWriter.java
+++ b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/model/ResourceWriter.java
@@ -99,7 +99,7 @@ public ServerMediaType serverMediaType() {
if (serverMediaType == null) {
synchronized (this) {
// a MessageBodyWriter should always return its configured media type when negotiating, hence the 'false' for 'useSuffix'
- serverMediaType = new ServerMediaType(mediaTypes(), StandardCharsets.UTF_8.name(), false, false);
+ serverMediaType = new ServerMediaType(mediaTypes(), StandardCharsets.UTF_8.name(), false);
}
}
return serverMediaType;
@@ -129,7 +129,15 @@ public String toString() {
*/
public static class ResourceWriterComparator implements Comparator {
- public static final ResourceWriterComparator INSTANCE = new ResourceWriterComparator();
+ private final List produces;
+
+ public ResourceWriterComparator() {
+ this(Collections.emptyList());
+ }
+
+ public ResourceWriterComparator(List produces) {
+ this.produces = produces;
+ }
@Override
public int compare(ResourceWriter o1, ResourceWriter o2) {
@@ -159,6 +167,14 @@ public int compare(ResourceWriter o1, ResourceWriter o2) {
return mediaTypeCompare;
}
+ // try to compare using the number of matching produces media types
+ if (!produces.isEmpty()) {
+ mediaTypeCompare = MediaTypeHelper.compareMatchingMediaTypes(produces, mediaTypes1, mediaTypes2);
+ if (mediaTypeCompare != 0) {
+ return mediaTypeCompare;
+ }
+ }
+
// done to make the sorting result deterministic
return Integer.compare(mediaTypes1.size(), mediaTypes2.size());
}
diff --git a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/util/MediaTypeHelper.java b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/util/MediaTypeHelper.java
index 41b72877f98085..f7e5e840067361 100644
--- a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/util/MediaTypeHelper.java
+++ b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/util/MediaTypeHelper.java
@@ -2,9 +2,11 @@
import java.io.Serializable;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
+import java.util.regex.Pattern;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@@ -16,6 +18,7 @@
public class MediaTypeHelper {
public static final MediaTypeComparator Q_COMPARATOR = new MediaTypeComparator("q");
public static final MediaTypeComparator QS_COMPARATOR = new MediaTypeComparator("qs");
+ private static final String MEDIA_TYPE_SUFFIX_DELIM = "+";
private static float getQTypeWithParamInfo(MediaType type, String parameterName) {
if (type.getParameters() != null) {
@@ -138,6 +141,13 @@ public static int compareWeight(MediaType one, MediaType two) {
return Q_COMPARATOR.compare(one, two);
}
+ public static int compareMatchingMediaTypes(List produces, List mediaTypes1,
+ List mediaTypes2) {
+ int countMediaTypes1 = countMatchingMediaTypes(produces, mediaTypes1);
+ int countMediaTypes2 = countMatchingMediaTypes(produces, mediaTypes2);
+ return (countMediaTypes1 < countMediaTypes2) ? 1 : ((countMediaTypes1 == countMediaTypes2) ? 0 : -1);
+ }
+
public static void sortByWeight(List types) {
if (hasAtMostOneItem(types)) {
return;
@@ -267,20 +277,77 @@ public static boolean isUnsupportedWildcardSubtype(MediaType mediaType) {
return false;
}
+ public static List toListOfMediaType(String[] mediaTypes) {
+ if (mediaTypes == null || mediaTypes.length == 0) {
+ return Collections.emptyList();
+ }
+
+ List list = new ArrayList<>(mediaTypes.length);
+ for (String mediaType : mediaTypes) {
+ list.add(MediaType.valueOf(mediaType));
+ }
+
+ return Collections.unmodifiableList(list);
+ }
+
+ /**
+ * This method ungroups the media types with suffix in separated media types. For example, having the media type
+ * "application/one+two" will return a list containing ["application/one+two", "application/one", "application/two"].
+ * The Media Types without suffix remain as one media type.
+ *
+ * @param mediaTypes the list of media types to separate.
+ * @return the list of ungrouped media types.
+ */
+ public static List getUngroupedMediaTypes(List mediaTypes) {
+ List effectiveMediaTypes = new ArrayList<>();
+ for (MediaType mediaType : mediaTypes) {
+ effectiveMediaTypes.addAll(getUngroupedMediaTypes(mediaType));
+ }
+
+ return Collections.unmodifiableList(effectiveMediaTypes);
+ }
+
/**
- * If the supplied media type contains a suffix in the subtype, then this returns a new media type
- * that uses the suffix as the subtype
+ * This method ungroups the media type with suffix in separated media types. For example, having the media type
+ * "application/one+two" will return a list containing ["application/one+two", "application/one", "application/two"].
+ * If the Media Type does not have a suffix, then it's not modified.
+ *
+ * @param mediaType the media type to separate.
+ * @return the list of ungrouped media types.
*/
- public static MediaType withSuffixAsSubtype(MediaType mediaType) {
+ public static List getUngroupedMediaTypes(MediaType mediaType) {
if (mediaType == null) {
- return null;
+ return Collections.emptyList();
+ }
+
+ if (mediaType.getSubtype() == null || !mediaType.getSubtype().contains(MEDIA_TYPE_SUFFIX_DELIM)) {
+ return Collections.singletonList(mediaType);
+ }
+
+ String[] subTypes = mediaType.getSubtype().split(Pattern.quote(MEDIA_TYPE_SUFFIX_DELIM));
+
+ List effectiveMediaTypes = new ArrayList<>(1 + subTypes.length);
+ effectiveMediaTypes.add(mediaType);
+ for (String subType : subTypes) {
+ effectiveMediaTypes.add(new MediaType(mediaType.getType(), subType, mediaType.getParameters()));
}
- int plusIndex = mediaType.getSubtype().indexOf('+');
- if ((plusIndex > -1) && (plusIndex < mediaType.getSubtype().length() - 1)) {
- mediaType = new MediaType(mediaType.getType(),
- mediaType.getSubtype().substring(plusIndex + 1),
- mediaType.getParameters());
+
+ return Collections.unmodifiableList(effectiveMediaTypes);
+ }
+
+ private static int countMatchingMediaTypes(List produces, List mediaTypes) {
+ int count = 0;
+ for (int i = 0; i < mediaTypes.size(); i++) {
+ MediaType mediaType = mediaTypes.get(i);
+ for (int j = 0; j < produces.size(); j++) {
+ MediaType produce = produces.get(j);
+ if (mediaType.isCompatible(produce)) {
+ count++;
+ break;
+ }
+ }
}
- return mediaType;
+
+ return count;
}
}
diff --git a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/util/ServerMediaType.java b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/util/ServerMediaType.java
index cff31dd2a32004..97ba2d2f174bef 100644
--- a/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/util/ServerMediaType.java
+++ b/independent-projects/resteasy-reactive/common/runtime/src/main/java/org/jboss/resteasy/reactive/common/util/ServerMediaType.java
@@ -30,14 +30,11 @@ public static List mediaTypesFromArray(String[] mediaTypesStrs) {
}
/**
- *
* @param mediaTypes The original media types
* @param charset charset to use
* @param deprioritizeWildcards whether or not wildcard types should be carry less weight when sorting is performed
- * @param useSuffix whether or not a media type whose subtype contains a suffix should swap the entire subtype with the
- * suffix
*/
- public ServerMediaType(List mediaTypes, String charset, boolean deprioritizeWildcards, boolean useSuffix) {
+ public ServerMediaType(List mediaTypes, String charset, boolean deprioritizeWildcards) {
if (mediaTypes.isEmpty()) {
this.sortedOriginalMediaTypes = new MediaType[] { MediaType.WILDCARD_TYPE };
} else {
@@ -87,12 +84,6 @@ public int compare(MediaType m1, MediaType m2) {
MediaType m = new MediaType(existing.getType(), existing.getSubtype(), charset);
sortedMediaTypes[i] = m;
}
- // use the suffix type if it exists when negotiating the type
- if (useSuffix) {
- for (int i = 0; i < sortedMediaTypes.length; i++) {
- sortedMediaTypes[i] = MediaTypeHelper.withSuffixAsSubtype(sortedMediaTypes[i]);
- }
- }
// if there is only one media type, use it
if (sortedMediaTypes.length == 1
&& !(sortedMediaTypes[0].isWildcardType() || sortedMediaTypes[0].isWildcardSubtype())) {
diff --git a/independent-projects/resteasy-reactive/pom.xml b/independent-projects/resteasy-reactive/pom.xml
index 999445da14c053..f4cb0c7ac1d759 100644
--- a/independent-projects/resteasy-reactive/pom.xml
+++ b/independent-projects/resteasy-reactive/pom.xml
@@ -54,7 +54,7 @@
1.6.8
2.0.1.Final
1.1.6
- 1.4.0
+ 1.5.0
1.12.0
4.2.4
4.5.1
@@ -66,7 +66,7 @@
1.0.11
1.0.2
4.2.0
- 2.19.0
+ 2.22.0
diff --git a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/serialization/DynamicEntityWriter.java b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/serialization/DynamicEntityWriter.java
index 4109b8e1182a7b..929017cdc6bd75 100644
--- a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/serialization/DynamicEntityWriter.java
+++ b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/serialization/DynamicEntityWriter.java
@@ -97,8 +97,7 @@ public void write(ResteasyReactiveRequestContext context, Object entity) throws
}
} else {
writers = serialisers
- .findWriters(null, entity.getClass(), MediaTypeHelper.withSuffixAsSubtype(producesMediaType.getMediaType()),
- RuntimeType.SERVER)
+ .findWriters(null, entity.getClass(), producesMediaType.getMediaType(), RuntimeType.SERVER)
.toArray(ServerSerialisers.NO_WRITER);
}
for (MessageBodyWriter> w : writers) {
diff --git a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/startup/RuntimeResourceDeployment.java b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/startup/RuntimeResourceDeployment.java
index 15c40b97948ffc..1685899412d99c 100644
--- a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/startup/RuntimeResourceDeployment.java
+++ b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/core/startup/RuntimeResourceDeployment.java
@@ -379,7 +379,7 @@ public RuntimeResource buildResourceMethod(ResourceClass clazz,
// when negotiating a media type, we want to use the proper subtype to locate a ResourceWriter,
// hence the 'true' for 'useSuffix'
serverMediaType = new ServerMediaType(ServerMediaType.mediaTypesFromArray(method.getProduces()),
- StandardCharsets.UTF_8.name(), false, true);
+ StandardCharsets.UTF_8.name(), false);
}
if (method.getHttpMethod() == null) {
//this is a resource locator method
@@ -399,8 +399,7 @@ public RuntimeResource buildResourceMethod(ResourceClass clazz,
} else if (rawEffectiveReturnType != Void.class
&& rawEffectiveReturnType != void.class) {
List> buildTimeWriters = serialisers.findBuildTimeWriters(rawEffectiveReturnType,
- RuntimeType.SERVER, Collections.singletonList(
- MediaTypeHelper.withSuffixAsSubtype(MediaType.valueOf(method.getProduces()[0]))));
+ RuntimeType.SERVER, MediaTypeHelper.toListOfMediaType(method.getProduces()));
if (buildTimeWriters == null) {
//if this is null this means that the type cannot be resolved at build time
//this happens when the method returns a generic type (e.g. Object), so there
diff --git a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/handlers/MediaTypeMapper.java b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/handlers/MediaTypeMapper.java
index 1d2bea0c749839..a77db34a0d847f 100644
--- a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/handlers/MediaTypeMapper.java
+++ b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/handlers/MediaTypeMapper.java
@@ -131,8 +131,9 @@ public void setResource(RuntimeResource runtimeResource, MediaType mediaType) {
}
public void setupServerMediaType() {
- MediaTypeHelper.sortByQSWeight(mtsWithParams); // TODO: this isn't completely correct as we are supposed to take q and then qs into account...
- serverMediaType = new ServerMediaType(mtsWithParams, StandardCharsets.UTF_8.name(), true, false);
+ // TODO: this isn't completely correct as we are supposed to take q and then qs into account...
+ MediaTypeHelper.sortByQSWeight(mtsWithParams);
+ serverMediaType = new ServerMediaType(mtsWithParams, StandardCharsets.UTF_8.name(), true);
}
}
}
diff --git a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/handlers/RequestDeserializeHandler.java b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/handlers/RequestDeserializeHandler.java
index 2a89c7b1f4c1de..d668916b5851d7 100644
--- a/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/handlers/RequestDeserializeHandler.java
+++ b/independent-projects/resteasy-reactive/server/runtime/src/main/java/org/jboss/resteasy/reactive/server/handlers/RequestDeserializeHandler.java
@@ -15,7 +15,6 @@
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.ReaderInterceptor;
import org.jboss.logging.Logger;
-import org.jboss.resteasy.reactive.common.util.MediaTypeHelper;
import org.jboss.resteasy.reactive.server.core.ResteasyReactiveRequestContext;
import org.jboss.resteasy.reactive.server.core.ServerSerialisers;
import org.jboss.resteasy.reactive.server.jaxrs.ReaderInterceptorContextImpl;
@@ -47,7 +46,7 @@ public void handle(ResteasyReactiveRequestContext requestContext) throws Excepti
String requestTypeString = requestContext.serverRequest().getRequestHeader(HttpHeaders.CONTENT_TYPE);
if (requestTypeString != null) {
try {
- effectiveRequestType = MediaTypeHelper.withSuffixAsSubtype(MediaType.valueOf(requestTypeString));
+ effectiveRequestType = MediaType.valueOf(requestTypeString);
} catch (Exception e) {
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST).build());
}
diff --git a/integration-tests/devtools/src/test/java/io/quarkus/platform/catalog/RegistrySnapshotCatalogCompatibilityTest.java b/integration-tests/devtools/src/test/java/io/quarkus/platform/catalog/CatalogCompatibilityTest.java
similarity index 81%
rename from integration-tests/devtools/src/test/java/io/quarkus/platform/catalog/RegistrySnapshotCatalogCompatibilityTest.java
rename to integration-tests/devtools/src/test/java/io/quarkus/platform/catalog/CatalogCompatibilityTest.java
index a67d1c24f0b724..84149c7f2d24e3 100644
--- a/integration-tests/devtools/src/test/java/io/quarkus/platform/catalog/RegistrySnapshotCatalogCompatibilityTest.java
+++ b/integration-tests/devtools/src/test/java/io/quarkus/platform/catalog/CatalogCompatibilityTest.java
@@ -5,17 +5,16 @@
import java.io.IOException;
import java.util.List;
-import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import io.quarkus.devtools.codestarts.quarkus.QuarkusCodestartCatalog;
import io.quarkus.devtools.project.CodestartResourceLoadersBuilder;
import io.quarkus.devtools.project.QuarkusProjectHelper;
+import io.quarkus.devtools.testing.PlatformAwareTestBase;
import io.quarkus.platform.catalog.processor.CatalogProcessor;
import io.quarkus.platform.catalog.processor.ExtensionProcessor;
import io.quarkus.platform.catalog.processor.ProcessedCategory;
import io.quarkus.platform.descriptor.loader.json.ResourceLoader;
-import io.quarkus.registry.Constants;
import io.quarkus.registry.ExtensionCatalogResolver;
import io.quarkus.registry.RegistryResolutionException;
import io.quarkus.registry.catalog.Extension;
@@ -25,20 +24,13 @@
import io.quarkus.registry.catalog.PlatformRelease;
import io.quarkus.registry.catalog.PlatformStream;
-public class RegistrySnapshotCatalogCompatibilityTest {
-
- private final ExtensionCatalogResolver catalogResolver = QuarkusProjectHelper.getCatalogResolver();
-
- public RegistrySnapshotCatalogCompatibilityTest() throws RegistryResolutionException {
- }
+public class CatalogCompatibilityTest extends PlatformAwareTestBase {
@Test
- @Disabled
- public void testRegistrySnapshotPlatformCatalog() throws RegistryResolutionException, IOException {
- // TODO Use a local snapshot of the registry for testing
- final PlatformCatalog platformCatalog = getRegistryPlatformCatalog();
- assertThat(platformCatalog.getMetadata().get(Constants.LAST_UPDATED)).isNotNull();
- testPlatformCatalog(catalogResolver, platformCatalog, "io.quarkus.platform");
+ void testCatalog() throws RegistryResolutionException, IOException {
+ final ExtensionCatalogResolver catalogResolver = QuarkusProjectHelper.getCatalogResolver();
+ testPlatformCatalog(catalogResolver, catalogResolver.resolvePlatformCatalog(),
+ "io.quarkus");
}
static void testPlatformCatalog(ExtensionCatalogResolver catalogResolver, PlatformCatalog platformCatalog,
@@ -55,7 +47,6 @@ static void testPlatformCatalog(ExtensionCatalogResolver catalogResolver, Platfo
for (PlatformRelease r : s.getReleases()) {
checkPlatformRelease(catalogResolver, r);
}
-
}
}
@@ -102,7 +93,4 @@ private static void checkExtensionProcessor(Extension e) {
extensionProcessor.getNonQuarkusBomOnly();
}
- private PlatformCatalog getRegistryPlatformCatalog() throws RegistryResolutionException {
- return catalogResolver.resolvePlatformCatalog();
- }
}
diff --git a/integration-tests/devtools/src/test/java/io/quarkus/platform/catalog/LocalCatalogCompatibilityTest.java b/integration-tests/devtools/src/test/java/io/quarkus/platform/catalog/LocalCatalogCompatibilityTest.java
deleted file mode 100644
index ec7e5056547825..00000000000000
--- a/integration-tests/devtools/src/test/java/io/quarkus/platform/catalog/LocalCatalogCompatibilityTest.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package io.quarkus.platform.catalog;
-
-import java.io.IOException;
-
-import org.junit.jupiter.api.Test;
-
-import io.quarkus.devtools.project.QuarkusProjectHelper;
-import io.quarkus.devtools.testing.PlatformAwareTestBase;
-import io.quarkus.registry.ExtensionCatalogResolver;
-import io.quarkus.registry.RegistryResolutionException;
-
-public class LocalCatalogCompatibilityTest extends PlatformAwareTestBase {
-
- @Test
- void testCatalog() throws RegistryResolutionException, IOException {
- final ExtensionCatalogResolver catalogResolver = QuarkusProjectHelper.getCatalogResolver();
- RegistrySnapshotCatalogCompatibilityTest.testPlatformCatalog(catalogResolver, catalogResolver.resolvePlatformCatalog(),
- "io.quarkus");
- }
-}
diff --git a/integration-tests/gradle/.gradle/gradle.properties b/integration-tests/gradle/.gradle/gradle.properties
new file mode 100644
index 00000000000000..5f1ed7bbe024ab
--- /dev/null
+++ b/integration-tests/gradle/.gradle/gradle.properties
@@ -0,0 +1 @@
+org.gradle.caching=true
\ No newline at end of file
diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/AddExtensionToSingleModuleKtsProjectTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/AddExtensionToSingleModuleKtsProjectTest.java
index ab7ea55623e5dc..b53b9f6b72f833 100644
--- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/AddExtensionToSingleModuleKtsProjectTest.java
+++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/AddExtensionToSingleModuleKtsProjectTest.java
@@ -40,7 +40,7 @@ public void testRemoveNonExistentExtension() throws IOException, URISyntaxExcept
final File projectDir = getProjectDir("add-remove-extension-single-module-kts");
BuildResult buildResult = runGradleWrapper(projectDir, "clean", "build");
- assertThat(buildResult.getTasks().get(":test")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(buildResult.getTasks().get(":test"))).isTrue();
final Path buildKts = projectDir.toPath().resolve("build.gradle.kts");
assertThat(buildKts).exists();
diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/AddExtensionToSingleModuleProjectTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/AddExtensionToSingleModuleProjectTest.java
index 9d6965d4547f69..3a163d5b5af347 100644
--- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/AddExtensionToSingleModuleProjectTest.java
+++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/AddExtensionToSingleModuleProjectTest.java
@@ -37,7 +37,7 @@ public void testRemoveNonExistentExtension() throws IOException, URISyntaxExcept
final File projectDir = getProjectDir("add-remove-extension-single-module");
BuildResult buildResult = runGradleWrapper(projectDir, "clean", "build");
- assertThat(buildResult.getTasks().get(":test")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(buildResult.getTasks().get(":test"))).isTrue();
final Path build = projectDir.toPath().resolve("build.gradle");
assertThat(build).exists();
diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/AdditionalSourceSetsTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/AdditionalSourceSetsTest.java
index e335167b4d681f..66c16390f524fe 100644
--- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/AdditionalSourceSetsTest.java
+++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/AdditionalSourceSetsTest.java
@@ -1,6 +1,6 @@
package io.quarkus.gradle;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.assertj.core.api.Assertions.assertThat;
import java.io.File;
import java.io.IOException;
@@ -18,7 +18,6 @@ public class AdditionalSourceSetsTest extends QuarkusGradleWrapperTestBase {
public void executeFunctionalTest() throws URISyntaxException, IOException, InterruptedException {
final File projectDir = getProjectDir("additional-source-sets");
BuildResult result = runGradleWrapper(projectDir, "functionalTest");
- assertEquals(BuildResult.SUCCESS_OUTCOME, result.getTasks().get(":functionalTest"),
- "Failed to run tests defined in an alternate test sources directory");
+ assertThat(BuildResult.isSuccessful(result.getTasks().get(":functionalTest"))).isTrue();
}
}
diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/AnnotationProcessorMultiModuleTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/AnnotationProcessorMultiModuleTest.java
index 3a43713c46cb56..156bccf71e9148 100644
--- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/AnnotationProcessorMultiModuleTest.java
+++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/AnnotationProcessorMultiModuleTest.java
@@ -14,6 +14,6 @@ public void shouldRunTestCorrectly() throws Exception {
BuildResult buildResult = runGradleWrapper(projectDir, "clean", "test");
- assertThat(buildResult.getTasks().get(":application:test")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(buildResult.getTasks().get(":application:test"))).isTrue();
}
}
diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/AnnotationProcessorSimpleModuleTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/AnnotationProcessorSimpleModuleTest.java
index 66a61bbc6b0488..07445b9415f88b 100644
--- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/AnnotationProcessorSimpleModuleTest.java
+++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/AnnotationProcessorSimpleModuleTest.java
@@ -15,7 +15,7 @@ public void shouldRunTestCorrectly() throws Exception {
BuildResult buildResult = runGradleWrapper(projectDir, "clean", "test");
- assertThat(buildResult.getTasks().get(":test")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(buildResult.getTasks().get(":test"))).isTrue();
}
@Test
@@ -24,7 +24,7 @@ public void shouldContainsPanacheMarkerFile() throws Exception {
BuildResult buildResult = runGradleWrapper(projectDir, "clean", "quarkusBuild");
- assertThat(buildResult.getTasks().get(":quarkusBuild")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(buildResult.getTasks().get(":quarkusBuild"))).isTrue();
File buildDir = new File(projectDir, "build");
Path metaInfDir = buildDir.toPath().resolve("classes").resolve("java").resolve("main").resolve("META-INF");
diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/ApplicationConfigurationTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/ApplicationConfigurationTest.java
index f44453718537c2..86def66f466ea3 100644
--- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/ApplicationConfigurationTest.java
+++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/ApplicationConfigurationTest.java
@@ -14,7 +14,7 @@ public void shouldSuccessfullyInjectApplicationConfigInTest() throws Exception {
BuildResult testResult = runGradleWrapper(projectDir, "clean", ":application:test");
- assertThat(testResult.getTasks().get(":application:test")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(testResult.getTasks().get(":application:test"))).isTrue();
}
}
diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/BeanInTestSourcesTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/BeanInTestSourcesTest.java
index 374e98927150a5..6e68885d1a152b 100644
--- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/BeanInTestSourcesTest.java
+++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/BeanInTestSourcesTest.java
@@ -12,6 +12,6 @@ public class BeanInTestSourcesTest extends QuarkusGradleWrapperTestBase {
public void testBasicMultiModuleBuild() throws Exception {
final File projectDir = getProjectDir("bean-in-testsources-project");
final BuildResult build = runGradleWrapper(projectDir, "clean", "test");
- assertThat(build.getTasks().get(":test")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(build.getTasks().get(":test"))).isTrue();
}
}
diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/BuildResult.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/BuildResult.java
index df3e5e432f49df..c1288e1e04cf3a 100644
--- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/BuildResult.java
+++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/BuildResult.java
@@ -12,6 +12,7 @@ public class BuildResult {
public static final String SUCCESS_OUTCOME = "SUCCESS";
public static final String UPTODATE_OUTCOME = "UP-TO-DATE";
+ public static final String FROM_CACHE = "FROM-CACHE";
private static final String TASK_RESULT_PREFIX = "> Task";
private Map tasks;
@@ -54,4 +55,8 @@ public Map getTasks() {
public String getOutput() {
return output;
}
+
+ public static boolean isSuccessful(String result) {
+ return SUCCESS_OUTCOME.equals(result) || FROM_CACHE.equals(result);
+ }
}
diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/CustomFileSystemProviderTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/CustomFileSystemProviderTest.java
index 983a91b3d7ca0b..266da97dce7033 100644
--- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/CustomFileSystemProviderTest.java
+++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/CustomFileSystemProviderTest.java
@@ -14,6 +14,6 @@ public void test() throws Exception {
final File projectDir = getProjectDir("custom-filesystem-provider");
BuildResult build = runGradleWrapper(projectDir, "clean", ":application:test");
- assertThat(build.getTasks().get(":application:test")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(build.getTasks().get(":application:test"))).isTrue();
}
}
diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/DependencyConstraintsTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/DependencyConstraintsTest.java
index a8070a019be233..366d71eaaca942 100644
--- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/DependencyConstraintsTest.java
+++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/DependencyConstraintsTest.java
@@ -15,7 +15,7 @@ public void shoudBuildProjectWithDependencyConstraint() throws Exception {
BuildResult buildResult = runGradleWrapper(projectDir, "clean", "quarkusBuild", "-Dquarkus.package.type=mutable-jar");
- assertThat(buildResult.getTasks().get(":quarkusBuild")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(buildResult.getTasks().get(":quarkusBuild"))).isTrue();
final File buildDir = new File(projectDir, "build");
final Path mainLib = buildDir.toPath().resolve("quarkus-app").resolve("lib").resolve("main");
diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/DependencyResolutionTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/DependencyResolutionTest.java
index 509cfb6d3d0fcc..de98f99ff7c94e 100644
--- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/DependencyResolutionTest.java
+++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/DependencyResolutionTest.java
@@ -16,6 +16,6 @@ public void shouldResolveDependencyVersionFromSuperConfigurationProject()
final BuildResult result = runGradleWrapper(projectDir, "clean", "quarkusBuild");
- assertThat(result.getTasks().get(":quarkusBuild")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(result.getTasks().get(":quarkusBuild"))).isTrue();
}
}
diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/InjectBeanFromTestConfigTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/InjectBeanFromTestConfigTest.java
index b052e66a3f05c7..69f233f720df12 100644
--- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/InjectBeanFromTestConfigTest.java
+++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/InjectBeanFromTestConfigTest.java
@@ -14,6 +14,6 @@ public void testBasicMultiModuleBuild() throws Exception {
final File projectDir = getProjectDir("inject-bean-from-test-config");
BuildResult build = runGradleWrapper(projectDir, "clean", ":application:test");
- assertThat(build.getTasks().get(":application:test")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(build.getTasks().get(":application:test"))).isTrue();
}
}
diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/IntegrationTestBuildTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/IntegrationTestBuildTest.java
index 1145c1a07f1c72..60c482b0f68cc0 100644
--- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/IntegrationTestBuildTest.java
+++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/IntegrationTestBuildTest.java
@@ -14,8 +14,8 @@ public void shouldRunIntegrationTestAsPartOfBuild() throws Exception {
BuildResult buildResult = runGradleWrapper(projectDir, "clean", "quarkusIntTest");
- assertThat(buildResult.getTasks().get(":test")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
- assertThat(buildResult.getTasks().get(":quarkusIntTest")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(buildResult.getTasks().get(":test"))).isTrue();
+ assertThat(BuildResult.isSuccessful(buildResult.getTasks().get(":quarkusIntTest"))).isTrue();
}
}
diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/JandexMultiModuleTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/JandexMultiModuleTest.java
index f27fe605878b6d..d05f5530edf703 100644
--- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/JandexMultiModuleTest.java
+++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/JandexMultiModuleTest.java
@@ -14,8 +14,8 @@ public void testBasicMultiModuleBuild() throws Exception {
final File projectDir = getProjectDir("jandex-basic-multi-module-project");
BuildResult build = runGradleWrapper(projectDir, "clean", ":application:quarkusBuild");
- assertThat(build.getTasks().get(":common:jandex")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
- assertThat(build.getTasks().get(":application:quarkusBuild")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(build.getTasks().get(":common:jandex"))).isTrue();
+ assertThat(BuildResult.isSuccessful(build.getTasks().get(":application:quarkusBuild"))).isTrue();
}
}
diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/KotlinGRPCProjectBuildTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/KotlinGRPCProjectBuildTest.java
index 1148f70087ca11..7651be57e8496b 100644
--- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/KotlinGRPCProjectBuildTest.java
+++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/KotlinGRPCProjectBuildTest.java
@@ -12,7 +12,7 @@ public class KotlinGRPCProjectBuildTest extends QuarkusGradleWrapperTestBase {
public void testBasicMultiModuleBuild() throws Exception {
final File projectDir = getProjectDir("kotlin-grpc-project");
final BuildResult build = runGradleWrapper(projectDir, "clean", "build");
- assertThat(build.getTasks().get(":quarkusGenerateCode")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
- assertThat(build.getTasks().get(":compileKotlin")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(build.getTasks().get(":quarkusGenerateCode"))).isTrue();
+ assertThat(BuildResult.isSuccessful(build.getTasks().get(":compileKotlin"))).isTrue();
}
}
diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/MultiModuleKotlinProjectBuildTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/MultiModuleKotlinProjectBuildTest.java
index 020037329c4819..ecb3fb0cd3d483 100644
--- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/MultiModuleKotlinProjectBuildTest.java
+++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/MultiModuleKotlinProjectBuildTest.java
@@ -12,7 +12,7 @@ public class MultiModuleKotlinProjectBuildTest extends QuarkusGradleWrapperTestB
public void testBasicMultiModuleBuild() throws Exception {
final File projectDir = getProjectDir("multi-module-kotlin-project");
final BuildResult build = runGradleWrapper(projectDir, "clean", "build");
- assertThat(build.getTasks().get(":quarkusGenerateCode")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
- assertThat(build.getTasks().get(":compileKotlin")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(build.getTasks().get(":quarkusGenerateCode"))).isTrue();
+ assertThat(BuildResult.isSuccessful(build.getTasks().get(":compileKotlin"))).isTrue();
}
}
diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/MultiSourceProjectTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/MultiSourceProjectTest.java
index 640b8569b9abbc..bd730977147144 100644
--- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/MultiSourceProjectTest.java
+++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/MultiSourceProjectTest.java
@@ -13,7 +13,7 @@ public void shouldRunTest() throws Exception {
final File projectDir = getProjectDir("multi-source-project");
final BuildResult buildResult = runGradleWrapper(projectDir, ":clean", ":test");
- assertThat(buildResult.getTasks().get(":test")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(buildResult.getTasks().get(":test"))).isTrue();
}
}
diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/QuarkusPluginFunctionalTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/QuarkusPluginFunctionalTest.java
index fa25471402d78b..686a25c1480cd9 100644
--- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/QuarkusPluginFunctionalTest.java
+++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/QuarkusPluginFunctionalTest.java
@@ -38,7 +38,7 @@ public void canBuild(SourceType sourceType) throws Exception {
BuildResult build = runGradleWrapper(projectRoot, "build", "--stacktrace");
- assertThat(build.getTasks().get(":build")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(build.getTasks().get(":build"))).isTrue();
// gradle build should not build the native image
assertThat(build.getTasks().get(":buildNative")).isNull();
Path buildDir = projectRoot.toPath().resolve("build");
@@ -51,7 +51,7 @@ public void canDetectUpToDateBuild() throws Exception {
createProject(SourceType.JAVA);
BuildResult firstBuild = runGradleWrapper(projectRoot, "quarkusBuild", "--stacktrace");
- assertThat(firstBuild.getTasks().get(":quarkusBuild")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(firstBuild.getTasks().get(":quarkusBuild"))).isTrue();
BuildResult secondBuild = runGradleWrapper(projectRoot, "quarkusBuild", "--stacktrace");
assertThat(secondBuild.getTasks().get(":quarkusBuild")).isEqualTo(BuildResult.UPTODATE_OUTCOME);
@@ -62,13 +62,13 @@ public void canDetectResourceChangeWhenBuilding() throws Exception {
createProject(SourceType.JAVA);
BuildResult firstBuild = runGradleWrapper(projectRoot, "quarkusBuild", "--stacktrace");
- assertThat(firstBuild.getTasks().get(":quarkusBuild")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(firstBuild.getTasks().get(":quarkusBuild"))).isTrue();
final File applicationProperties = projectRoot.toPath().resolve("src/main/resources/application.properties").toFile();
Files.write(applicationProperties.toPath(), "quarkus.http.port=8888".getBytes());
BuildResult secondBuild = runGradleWrapper(projectRoot, "quarkusBuild", "--stacktrace");
- assertThat(secondBuild.getTasks().get(":quarkusBuild")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(secondBuild.getTasks().get(":quarkusBuild"))).isTrue();
}
@Test
@@ -76,14 +76,14 @@ public void canDetectClassChangeWhenBuilding() throws Exception {
createProject(SourceType.JAVA);
BuildResult firstBuild = runGradleWrapper(projectRoot, "quarkusBuild", "--stacktrace");
- assertThat(firstBuild.getTasks().get(":quarkusBuild")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(firstBuild.getTasks().get(":quarkusBuild"))).isTrue();
final File greetingResourceFile = projectRoot.toPath().resolve("src/main/java/org/acme/foo/GreetingResource.java")
.toFile();
DevModeTestUtils.filter(greetingResourceFile, ImmutableMap.of("\"/greeting\"", "\"/test/hello\""));
BuildResult secondBuild = runGradleWrapper(projectRoot, "quarkusBuild", "--stacktrace");
- assertThat(secondBuild.getTasks().get(":quarkusBuild")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(secondBuild.getTasks().get(":quarkusBuild"))).isTrue();
}
@Test
@@ -91,11 +91,11 @@ public void canDetectClasspathChangeWhenBuilding() throws Exception {
createProject(SourceType.JAVA);
BuildResult firstBuild = runGradleWrapper(projectRoot, "quarkusBuild", "--stacktrace");
- assertThat(firstBuild.getTasks().get(":quarkusBuild")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(firstBuild.getTasks().get(":quarkusBuild"))).isTrue();
runGradleWrapper(projectRoot, "addExtension", "--extensions=hibernate-orm");
BuildResult secondBuild = runGradleWrapper(projectRoot, "quarkusBuild", "--stacktrace");
- assertThat(secondBuild.getTasks().get(":quarkusBuild")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(secondBuild.getTasks().get(":quarkusBuild"))).isTrue();
}
@Test
@@ -104,13 +104,13 @@ public void canDetectOutputChangeWhenBuilding() throws Exception {
BuildResult firstBuild = runGradleWrapper(projectRoot, "quarkusBuild", "--stacktrace");
- assertThat(firstBuild.getTasks().get(":quarkusBuild")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(firstBuild.getTasks().get(":quarkusBuild"))).isTrue();
Path runnerJar = projectRoot.toPath().resolve("build").resolve("quarkus-app").resolve("quarkus-run.jar");
Files.delete(runnerJar);
BuildResult secondBuild = runGradleWrapper(projectRoot, "quarkusBuild", "--stacktrace");
- assertThat(secondBuild.getTasks().get(":quarkusBuild")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(secondBuild.getTasks().get(":quarkusBuild"))).isTrue();
assertThat(runnerJar).exists();
}
@@ -120,7 +120,7 @@ public void canDetectUpToDateTests() throws Exception {
BuildResult firstBuild = runGradleWrapper(projectRoot, "test");
- assertThat(firstBuild.getTasks().get(":test")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(firstBuild.getTasks().get(":test"))).isTrue();
BuildResult secondBuild = runGradleWrapper(projectRoot, "test");
@@ -133,12 +133,12 @@ public void canDetectSystemPropertyChangeWhenBuilding() throws Exception {
BuildResult firstBuild = runGradleWrapper(projectRoot, "quarkusBuild", "--stacktrace");
- assertThat(firstBuild.getTasks().get(":quarkusBuild")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(firstBuild.getTasks().get(":quarkusBuild"))).isTrue();
assertThat(projectRoot.toPath().resolve("build").resolve("quarkus-app").resolve("quarkus-run.jar")).exists();
BuildResult secondBuild = runGradleWrapper(projectRoot, "quarkusBuild", "-Dquarkus.package.type=fast-jar");
- assertThat(secondBuild.getTasks().get(":quarkusBuild")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(secondBuild.getTasks().get(":quarkusBuild"))).isTrue();
assertThat(projectRoot.toPath().resolve("build").resolve("quarkus-app")).exists();
}
@@ -148,7 +148,7 @@ public void canRunTest() throws Exception {
BuildResult buildResult = runGradleWrapper(projectRoot, "test", "--stacktrace");
- assertThat(buildResult.getTasks().get(":test")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(buildResult.getTasks().get(":test"))).isTrue();
}
@Test
@@ -158,7 +158,7 @@ public void generateCodeBeforeTests() throws Exception {
BuildResult firstBuild = runGradleWrapper(projectRoot, "test", "--stacktrace");
assertThat(firstBuild.getOutput()).contains("Task :quarkusGenerateCode");
assertThat(firstBuild.getOutput()).contains("Task :quarkusGenerateCodeTests");
- assertThat(firstBuild.getTasks().get(":test")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(firstBuild.getTasks().get(":test"))).isTrue();
}
private void createProject(SourceType sourceType) throws Exception {
diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/SpringDependencyManagementTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/SpringDependencyManagementTest.java
index b36c10a82019b2..36ff0a9dee4b88 100644
--- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/SpringDependencyManagementTest.java
+++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/SpringDependencyManagementTest.java
@@ -17,6 +17,6 @@ public void testQuarkusBuildShouldWorkWithSpringDependencyManagement()
final BuildResult result = runGradleWrapper(projectDir, "clean", "quarkusBuild");
- assertThat(result.getTasks().get(":quarkusBuild")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(result.getTasks().get(":quarkusBuild"))).isTrue();
}
}
diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/TestFixtureModuleTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/TestFixtureModuleTest.java
index 2b60e9226ef1a2..92f0a90f36350a 100644
--- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/TestFixtureModuleTest.java
+++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/TestFixtureModuleTest.java
@@ -16,6 +16,6 @@ public void testTaskShouldUseTestFixtures() throws IOException, URISyntaxExcepti
final BuildResult result = runGradleWrapper(projectDir, "clean", "test");
- assertThat(result.getTasks().get(":test")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(result.getTasks().get(":test"))).isTrue();
}
}
diff --git a/integration-tests/gradle/src/test/java/io/quarkus/gradle/TestFixtureMultiModuleTest.java b/integration-tests/gradle/src/test/java/io/quarkus/gradle/TestFixtureMultiModuleTest.java
index 00d9076bdca267..b48cbfda403ff3 100644
--- a/integration-tests/gradle/src/test/java/io/quarkus/gradle/TestFixtureMultiModuleTest.java
+++ b/integration-tests/gradle/src/test/java/io/quarkus/gradle/TestFixtureMultiModuleTest.java
@@ -14,6 +14,6 @@ public class TestFixtureMultiModuleTest extends QuarkusGradleWrapperTestBase {
public void testTaskShouldUseTestFixtures() throws IOException, URISyntaxException, InterruptedException {
final File projectDir = getProjectDir("test-fixtures-multi-module");
final BuildResult result = runGradleWrapper(projectDir, "clean", "test");
- assertThat(result.getTasks().get(":application:test")).isEqualTo(BuildResult.SUCCESS_OUTCOME);
+ assertThat(BuildResult.isSuccessful(result.getTasks().get(":application:test"))).isTrue();
}
}