Skip to content

Commit

Permalink
Don't fail with "Can't generate Hal endpoints" if there are no resources
Browse files Browse the repository at this point in the history
Fix quarkusio#26318

Note that I haven't added any tests as there are already existing coverage that verifies this continue working fine.
  • Loading branch information
Sgitario committed Jun 27, 2022
1 parent 5237b7d commit 3079078
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ public class ResteasyCommonProcessor {
private static final DotName QUARKUS_JSONB_SERIALIZER = DotName
.createSimple("io.quarkus.resteasy.common.runtime.jsonb.QuarkusJsonbSerializer");

private static final String APPLICATION_HAL_JSON = "application/hal+json";

private static final String[] WILDCARD_MEDIA_TYPE_ARRAY = { MediaType.WILDCARD };

private ResteasyCommonConfig resteasyCommonConfig;
Expand Down Expand Up @@ -217,7 +219,8 @@ JaxrsProvidersToRegisterBuildItem setupProviders(BuildProducer<ReflectiveClassBu
boolean needJsonSupport = restJsonSupportNeeded(indexBuildItem, ResteasyDotNames.CONSUMES)
|| restJsonSupportNeeded(indexBuildItem, ResteasyDotNames.PRODUCES)
|| restJsonSupportNeeded(indexBuildItem, ResteasyDotNames.RESTEASY_SSE_ELEMENT_TYPE)
|| restJsonSupportNeeded(indexBuildItem, ResteasyDotNames.RESTEASY_PART_TYPE);
|| restJsonSupportNeeded(indexBuildItem, ResteasyDotNames.RESTEASY_PART_TYPE)
|| restJsonSupportNeededForHalCapability(capabilities, indexBuildItem);
if (needJsonSupport) {
LOGGER.warn(
"Quarkus detected the need of REST JSON support but you have not provided the necessary JSON " +
Expand Down Expand Up @@ -390,21 +393,36 @@ private void checkProperConfigAccessInProvider(AnnotationInstance instance) {
}
}

private boolean restJsonSupportNeededForHalCapability(Capabilities capabilities, CombinedIndexBuildItem indexBuildItem) {
return capabilities.isPresent(Capability.HAL)
&& isMediaTypeFoundInAnnotation(indexBuildItem, ResteasyDotNames.PRODUCES, APPLICATION_HAL_JSON);
}

private boolean restJsonSupportNeeded(CombinedIndexBuildItem indexBuildItem, DotName mediaTypeAnnotation) {
return isMediaTypeFoundInAnnotation(indexBuildItem, mediaTypeAnnotation,
MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON_PATCH_JSON);
}

private boolean isMediaTypeFoundInAnnotation(CombinedIndexBuildItem indexBuildItem, DotName mediaTypeAnnotation,
String... mediaTypes) {
for (AnnotationInstance annotationInstance : indexBuildItem.getIndex().getAnnotations(mediaTypeAnnotation)) {
final AnnotationValue annotationValue = annotationInstance.value();
if (annotationValue == null) {
continue;
}

List<String> mediaTypes = Collections.emptyList();
List<String> foundMediaTypes = Collections.emptyList();
if (annotationValue.kind() == Kind.ARRAY) {
mediaTypes = Arrays.asList(annotationValue.asStringArray());
foundMediaTypes = Arrays.asList(annotationValue.asStringArray());
} else if (annotationValue.kind() == Kind.STRING) {
mediaTypes = Collections.singletonList(annotationValue.asString());
foundMediaTypes = Collections.singletonList(annotationValue.asString());
}

for (int i = 0; i < mediaTypes.length; i++) {
if (foundMediaTypes.contains(mediaTypes[i])) {
return true;
}
}
return mediaTypes.contains(MediaType.APPLICATION_JSON)
|| mediaTypes.contains(MediaType.APPLICATION_JSON_PATCH_JSON);
}

return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,6 @@ void addHalSupport(Capabilities capabilities, BuildProducer<ResteasyJaxrsProvide
BuildProducer<AdditionalBeanBuildItem> additionalBeans) {
boolean isHalSupported = capabilities.isPresent(Capability.HAL);
if (isHalSupported) {
if (!capabilities.isPresent(Capability.RESTEASY_JSON_JSONB)
&& !capabilities.isPresent(Capability.RESTEASY_JSON_JACKSON)) {
throw new IllegalStateException("Cannot generate HAL endpoints without "
+ "either 'quarkus-resteasy-jsonb' or 'quarkus-resteasy-jackson'");
}

jaxRsProviders.produce(
new ResteasyJaxrsProviderBuildItem(HalServerResponseFilter.class.getName()));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.jboss.jandex.DotName;
import org.jboss.jandex.FieldInfo;
import org.jboss.jandex.IndexView;
import org.jboss.resteasy.reactive.common.util.RestMediaType;

import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
import io.quarkus.deployment.Capabilities;
Expand Down Expand Up @@ -82,23 +83,44 @@ AdditionalBeanBuildItem registerRestLinksProviderProducer() {
}

@BuildStep
void addHalSupport(Capabilities capabilities, BuildProducer<CustomContainerResponseFilterBuildItem> customResponseFilters,
BuildProducer<AdditionalBeanBuildItem> additionalBeans) {
void validateJsonNeededForHal(Capabilities capabilities,
ResteasyReactiveResourceMethodEntriesBuildItem resourceMethodEntriesBuildItem) {
boolean isHalSupported = capabilities.isPresent(Capability.HAL);
if (isHalSupported) {
if (isHalSupported && isHalMediaTypeUsedInAnyResource(resourceMethodEntriesBuildItem.getEntries())) {

if (!capabilities.isPresent(Capability.RESTEASY_REACTIVE_JSON_JSONB) && !capabilities.isPresent(
Capability.RESTEASY_REACTIVE_JSON_JACKSON)) {
throw new IllegalStateException("Cannot generate HAL endpoints without "
+ "either 'quarkus-resteasy-reactive-jsonb' or 'quarkus-resteasy-reactive-jackson'");
}
}
}

@BuildStep
void addHalSupport(Capabilities capabilities,
BuildProducer<CustomContainerResponseFilterBuildItem> customResponseFilters,
BuildProducer<AdditionalBeanBuildItem> additionalBeans) {
boolean isHalSupported = capabilities.isPresent(Capability.HAL);
if (isHalSupported) {
customResponseFilters.produce(
new CustomContainerResponseFilterBuildItem(HalServerResponseFilter.class.getName()));

additionalBeans.produce(AdditionalBeanBuildItem.unremovableOf(ResteasyReactiveHalService.class));
}
}

private boolean isHalMediaTypeUsedInAnyResource(List<ResteasyReactiveResourceMethodEntriesBuildItem.Entry> entries) {
for (ResteasyReactiveResourceMethodEntriesBuildItem.Entry entry : entries) {
for (String mediaType : entry.getResourceMethod().getProduces()) {
if (RestMediaType.APPLICATION_HAL_JSON.equals(mediaType)) {
return true;
}
}
}

return false;
}

private LinksContainer getLinksContainer(ResteasyReactiveResourceMethodEntriesBuildItem resourceMethodEntriesBuildItem,
IndexView index) {
LinksContainerFactory linksContainerFactory = new LinksContainerFactory();
Expand Down

0 comments on commit 3079078

Please sign in to comment.