11package io .quarkus .resteasy .reactive .jaxb .deployment ;
22
3+ import static org .jboss .resteasy .reactive .common .processor .ResteasyReactiveDotNames .REST_RESPONSE ;
4+
35import java .util .ArrayList ;
46import java .util .Collection ;
57import java .util .Collections ;
810import java .util .Locale ;
911import java .util .Set ;
1012
13+ import jakarta .enterprise .inject .spi .DeploymentException ;
1114import jakarta .ws .rs .Priorities ;
1215import jakarta .ws .rs .RuntimeType ;
1316import jakarta .ws .rs .core .MediaType ;
1922import org .jboss .jandex .FieldInfo ;
2023import org .jboss .jandex .IndexView ;
2124import org .jboss .jandex .MethodInfo ;
25+ import org .jboss .jandex .MethodParameterInfo ;
2226import org .jboss .jandex .Type ;
27+ import org .jboss .resteasy .reactive .common .model .MethodParameter ;
28+ import org .jboss .resteasy .reactive .common .model .ParameterType ;
2329import org .jboss .resteasy .reactive .common .model .ResourceMethod ;
2430import org .jboss .resteasy .reactive .common .processor .ResteasyReactiveDotNames ;
2531
@@ -87,6 +93,13 @@ void registerClassesToBeBound(ResteasyReactiveResourceMethodEntriesBuildItem res
8793 if (effectiveReturnType != null ) {
8894 // When using "application/xml", the return type needs to be registered
8995 if (producesXml (resourceInfo )) {
96+ if (!isTypeCompatibleWithJaxb (methodInfo .returnType ())) {
97+ throw new DeploymentException (
98+ "Cannot directly return collections or arrays using JAXB. You need to wrap it "
99+ + "into a root element class. Problematic method is '"
100+ + entry .getActualClassInfo ().name () + "." + methodInfo .name () + "'" );
101+ }
102+
90103 classesInfo .add (effectiveReturnType );
91104 }
92105
@@ -100,8 +113,16 @@ void registerClassesToBeBound(ResteasyReactiveResourceMethodEntriesBuildItem res
100113 boolean consumesXml = consumesXml (resourceInfo );
101114 boolean consumesMultipart = consumesMultipart (resourceInfo );
102115 if (consumesXml || consumesMultipart ) {
103- for (Type parameter : methodInfo .parameterTypes ()) {
104- ClassInfo effectiveParameter = getEffectiveClassInfo (parameter , indexView );
116+ for (MethodParameterInfo parameter : methodInfo .parameters ()) {
117+ if (isParameterBody (parameter , resourceInfo ) && !isTypeCompatibleWithJaxb (parameter .type ())) {
118+ throw new DeploymentException (
119+ "Cannot handle collections or arrays as parameters using JAXB. You need to wrap it "
120+ + "into a root element class. Problematic parameter is '" + parameter .name ()
121+ + "' in the method '" + entry .getActualClassInfo ().name () + "." + methodInfo .name ()
122+ + "'" );
123+ }
124+
125+ ClassInfo effectiveParameter = getEffectiveClassInfo (parameter .type (), indexView );
105126 if (effectiveParameter != null ) {
106127 if (consumesXml ) {
107128 classesInfo .add (effectiveParameter );
@@ -154,23 +175,16 @@ private ClassInfo getEffectiveClassInfo(Type type, IndexView indexView) {
154175 }
155176
156177 Type effectiveType = type ;
157- if (effectiveType .name ().equals (ResteasyReactiveDotNames .REST_RESPONSE ) ||
158- effectiveType .name ().equals (ResteasyReactiveDotNames .UNI ) ||
159- effectiveType .name ().equals (ResteasyReactiveDotNames .COMPLETABLE_FUTURE ) ||
160- effectiveType .name ().equals (ResteasyReactiveDotNames .COMPLETION_STAGE ) ||
161- effectiveType .name ().equals (ResteasyReactiveDotNames .REST_MULTI ) ||
162- effectiveType .name ().equals (ResteasyReactiveDotNames .MULTI )) {
178+ if (isContainerType (effectiveType )) {
163179 if (effectiveType .kind () != Type .Kind .PARAMETERIZED_TYPE ) {
164180 return null ;
165181 }
166182
167183 effectiveType = type .asParameterizedType ().arguments ().get (0 );
168184 }
169- if (effectiveType .name ().equals (ResteasyReactiveDotNames .SET ) ||
170- effectiveType .name ().equals (ResteasyReactiveDotNames .COLLECTION ) ||
171- effectiveType .name ().equals (ResteasyReactiveDotNames .LIST )) {
185+ if (isCollectionType (effectiveType )) {
172186 effectiveType = effectiveType .asParameterizedType ().arguments ().get (0 );
173- } else if (effectiveType . name (). equals ( ResteasyReactiveDotNames . MAP )) {
187+ } else if (isMapType ( effectiveType )) {
174188 effectiveType = effectiveType .asParameterizedType ().arguments ().get (1 );
175189 }
176190
@@ -220,4 +234,53 @@ private List<String> toClasses(Collection<ClassInfo> classesInfo) {
220234
221235 return classes ;
222236 }
237+
238+ private boolean isParameterBody (MethodParameterInfo parameter , ResourceMethod resourceInfo ) {
239+ for (MethodParameter parameterInfo : resourceInfo .getParameters ()) {
240+ if (parameterInfo .name != null && parameterInfo .name .equals (parameter .name ())) {
241+ return parameterInfo .parameterType == ParameterType .BODY ;
242+ }
243+ }
244+
245+ return false ;
246+ }
247+
248+ private boolean isCollectionType (Type type ) {
249+ return type .name ().equals (ResteasyReactiveDotNames .SET ) ||
250+ type .name ().equals (ResteasyReactiveDotNames .COLLECTION ) ||
251+ type .name ().equals (ResteasyReactiveDotNames .LIST );
252+ }
253+
254+ private boolean isMapType (Type type ) {
255+ return type .name ().equals (ResteasyReactiveDotNames .MAP );
256+ }
257+
258+ private boolean isContainerType (Type type ) {
259+ return type .name ().equals (REST_RESPONSE ) ||
260+ type .name ().equals (ResteasyReactiveDotNames .UNI ) ||
261+ type .name ().equals (ResteasyReactiveDotNames .COMPLETABLE_FUTURE ) ||
262+ type .name ().equals (ResteasyReactiveDotNames .COMPLETION_STAGE ) ||
263+ type .name ().equals (ResteasyReactiveDotNames .REST_MULTI ) ||
264+ type .name ().equals (ResteasyReactiveDotNames .MULTI );
265+ }
266+
267+ private boolean isTypeCompatibleWithJaxb (Type type ) {
268+ if (type .kind () == Type .Kind .PRIMITIVE ) {
269+ return true ;
270+ }
271+
272+ if (type .kind () == Type .Kind .ARRAY || isCollectionType (type ) || isMapType (type )) {
273+ return false ;
274+ }
275+
276+ if (isContainerType (type )) {
277+ if (type .kind () != Type .Kind .PARAMETERIZED_TYPE ) {
278+ return true ;
279+ }
280+
281+ return isTypeCompatibleWithJaxb (type .asParameterizedType ().arguments ().get (0 ));
282+ }
283+
284+ return true ;
285+ }
223286}
0 commit comments