Skip to content

Commit

Permalink
Merge pull request #657 from MikeEdgar/650_unwrap_jaxbelement_type_2.0.x
Browse files Browse the repository at this point in the history
Unwrap generic type from JAXBElement (2.0.x)
  • Loading branch information
phillip-kruger authored Feb 5, 2021
2 parents 22b88c6 + 453120b commit 4b6956f
Show file tree
Hide file tree
Showing 12 changed files with 94 additions and 20 deletions.
6 changes: 6 additions & 0 deletions core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@
<artifactId>jakarta.annotation-api</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>jakarta.xml.bind</groupId>
<artifactId>jakarta.xml.bind-api</artifactId>
<version>${version.jakarta.xml.bind.api}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
*/
public class JaxbConstants {

public static final DotName JAXB_ELEMENT = DotName
.createSimple("javax.xml.bind.JAXBElement");
public static final DotName XML_TYPE = DotName
.createSimple("javax.xml.bind.annotation.XmlType");
public static final DotName XML_ELEMENT = DotName
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -401,9 +401,9 @@ public static Schema typeToSchema(final AnnotationScannerContext context, Type t
List<AnnotationScannerExtension> extensions) {
Schema schema = null;

if (TypeUtil.isOptional(type)) {
if (TypeUtil.isWrappedType(type)) {
// Recurse using the optional's type
return typeToSchema(context, TypeUtil.getOptionalType(type), extensions);
return typeToSchema(context, TypeUtil.unwrapType(type), extensions);
} else if (CurrentScannerInfo.isWrapperType(type)) {
// Recurse using the wrapped type
return typeToSchema(context, CurrentScannerInfo.getCurrentAnnotationScanner().unwrapType(type), extensions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ Schema processField() {
TypeUtil.applyTypeAttributes(fieldType, typeSchema);

// The registeredTypeSchema will be a reference to typeSchema if registration occurs
Type registrationType = TypeUtil.isOptional(entityType) ? fieldType : entityType;
Type registrationType = TypeUtil.isWrappedType(entityType) ? fieldType : entityType;

if (typeSchema.getType() != SchemaType.ARRAY) {
// Only register a reference to the type schema. The full schema will be added by subsequent
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,12 @@ public Type processType() {
return arrayType;
}

if (TypeUtil.isOptional(type)) {
Type optType = TypeUtil.getOptionalType(type);
if (!isTerminalType(optType) && index.containsClass(optType)) {
pushToStack(optType);
if (TypeUtil.isWrappedType(type)) {
Type wrappedType = TypeUtil.unwrapType(type);
if (!isTerminalType(wrappedType) && index.containsClass(wrappedType)) {
pushToStack(wrappedType);
}
return optType;
return wrappedType;
}

if (isA(type, ENUM_TYPE) && index.containsClass(type)) {
Expand Down
21 changes: 21 additions & 0 deletions core/src/main/java/io/smallrye/openapi/runtime/util/TypeUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import org.jboss.jandex.WildcardType;

import io.smallrye.openapi.api.constants.JDKConstants;
import io.smallrye.openapi.api.constants.JaxbConstants;
import io.smallrye.openapi.api.constants.OpenApiConstants;
import io.smallrye.openapi.api.models.ExternalDocumentationImpl;
import io.smallrye.openapi.runtime.io.externaldocs.ExternalDocsConstant;
Expand Down Expand Up @@ -453,6 +454,26 @@ public static boolean isTerminalType(Type type) {
return !getTypeFormat(type).isSchemaType(SchemaType.ARRAY, SchemaType.OBJECT);
}

public static boolean isWrappedType(Type type) {
if (type != null) {
return isOptional(type) || JaxbConstants.JAXB_ELEMENT.equals(type.name());
}
return false;
}

public static Type unwrapType(Type type) {
if (type != null) {
if (isOptional(type)) {
return getOptionalType(type);
}
if (JaxbConstants.JAXB_ELEMENT.equals(type.name())) {
return type.asParameterizedType().arguments().get(0);
}
}

return type;
}

/**
* Determine if a given type is one of the following types:
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@
import java.util.Collections;
import java.util.List;

import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlType;

import org.eclipse.microprofile.openapi.annotations.media.DiscriminatorMapping;
import org.eclipse.microprofile.openapi.annotations.media.Schema;
import org.eclipse.microprofile.openapi.models.OpenAPI;
Expand Down Expand Up @@ -240,4 +246,33 @@ public int getCurrentItemCount() {
}
}
}

/****************************************************************/

/*
* Test case derived from original example in Smallrye OpenAPI issue #650.
*
* https://github.com/smallrye/smallrye-open-api/issues/650
*/
@Test
public void testJaxbElementUnwrapped() throws IOException, JSONException {
Index index = indexOf(JAXBElementDto.class);
OpenApiAnnotationScanner scanner = new OpenApiAnnotationScanner(emptyConfig(), index);
OpenAPI result = scanner.scan();
printToConsole(result);
assertJsonEquals("components.schemas.jaxbelement-generic-type-unwrapped.json", result);
}

@Schema
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "JAXBElementDto", propOrder = {
"caseSubtitleFree",
"caseSubtitle"
})
static class JAXBElementDto {
@XmlElementRef(name = "CaseSubtitle", namespace = "urn:Milo.API.Miljo.DataContracts.V1", type = JAXBElement.class, required = false)
protected JAXBElement<String> caseSubtitle;
@XmlElementRef(name = "CaseSubtitleFree", namespace = "urn:Milo.API.Miljo.DataContracts.V1", type = JAXBElement.class, required = false)
protected JAXBElement<String> caseSubtitleFree;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"openapi": "3.0.3",
"components": {
"schemas": {
"JAXBElementDto": {
"type": "object",
"properties": {
"caseSubtitleFree": {
"type": "string"
},
"caseSubtitle": {
"type": "string"
}
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -201,10 +201,7 @@ protected void readAnnotatedType(AnnotationInstance annotation, AnnotationInstan
} else if (target != null) {
// This is a @BeanParam or a RESTEasy @MultipartForm
setMediaType(frameworkParam);

if (TypeUtil.isOptional(targetType)) {
targetType = TypeUtil.getOptionalType(targetType);
}
targetType = TypeUtil.unwrapType(targetType);

if (targetType != null) {
ClassInfo beanParam = index.getClassByName(targetType.name());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,7 @@ protected void readAnnotatedType(AnnotationInstance annotation, AnnotationInstan
} else if (target != null) {
// This is a @BeanParam or a RESTEasy @MultipartForm
setMediaType(frameworkParam);

if (TypeUtil.isOptional(targetType)) {
targetType = TypeUtil.getOptionalType(targetType);
}
targetType = TypeUtil.unwrapType(targetType);

if (targetType != null) {
ClassInfo beanParam = index.getClassByName(targetType.name());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,7 @@ private void readAnnotatedType(FrameworkParameter frameworkParam, AnnotationInst
} else if (target != null) {
// This is a @BeanParam or a RESTEasy @MultipartForm
setMediaType(frameworkParam);

if (TypeUtil.isOptional(targetType)) {
targetType = TypeUtil.getOptionalType(targetType);
}
targetType = TypeUtil.unwrapType(targetType);

if (targetType != null) {
ClassInfo beanParam = index.getClassByName(targetType.name());
Expand Down
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
<version.org.skyscreamer>1.5.0</version.org.skyscreamer>
<version.maven-resources-plugin>3.2.0</version.maven-resources-plugin>
<version.com.github.eirslett.frontend-maven-plugin>1.11.0</version.com.github.eirslett.frontend-maven-plugin>
<version.jakarta.xml.bind.api>2.3.3</version.jakarta.xml.bind.api>

<version.arquillian.jetty>1.0.0.CR3</version.arquillian.jetty>
<version.jetty>9.3.29.v20201019</version.jetty>
Expand Down

0 comments on commit 4b6956f

Please sign in to comment.