JUNEAU-180 Incorrect Swagger on Spring Boot methods that return
Collections of beans.
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
index 1826aa3..d2d4245 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
@@ -366,6 +366,10 @@
Class<T> c = innerClass;
ci = ClassInfo.of(c);
+ if (ci.isProxy()) {
+ ci = ci.getProxyFor();
+ innerClass = this.innerClass = ci.inner();
+ }
if (c.isPrimitive()) {
if (c == Boolean.TYPE)
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java
index 2e5760d..4f591a2 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java
@@ -216,28 +216,12 @@
*/
public ClassInfo resolved() {
if (Value.isType(t))
- return of(Value.getParameterType(t));
- return this;
+ return of(Value.getParameterType(t)).getProxiedClassInfo();
+ return getProxiedClassInfo();
}
- /**
- * Identifies the inner target class when this class info represents a CGLIB proxy class.
- *
- * @param proxyFor The inner non-proxied class.
- * @return This object (for method chaining).
- */
- public ClassInfo proxyFor(Class<?> proxyFor) {
- this.proxyFor = ClassInfo.of(proxyFor);
- return this;
- }
-
- /**
- * Returns the non-proxied inner class of a CGLIB proxy class.
- *
- * @return The non-proxied inner class of a CGLIB proxy class, or the inner class if it's not a proxy.
- */
- public Class<?> getProxiedClass() {
- return proxyFor == null ? c : proxyFor.inner();
+ private ClassInfo getProxiedClassInfo() {
+ return proxyFor == null ? this : proxyFor;
}
//-----------------------------------------------------------------------------------------------------------------
@@ -2093,6 +2077,24 @@
}
/**
+ * Returns <jk>true</jk> if this class is a proxy for another class.
+ *
+ * @return <jk>true</jk> if this class is a proxy for another class.
+ */
+ public boolean isProxy() {
+ return proxyFor != null;
+ }
+
+ /**
+ * Returns the class info of the proxied class.
+ *
+ * @return The class info of the proxied class, or <jk>null</jk> if this class is not proxied.
+ */
+ public ClassInfo getProxyFor() {
+ return proxyFor;
+ }
+
+ /**
* Returns the number of dimensions if this is an array type.
*
* @return The number of dimensions if this is an array type, or <c>0</c> if it is not.
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestInfoProvider.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestInfoProvider.java
index 66871cf..b42a1e1 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestInfoProvider.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/BasicRestInfoProvider.java
@@ -67,7 +67,7 @@
@SuppressWarnings("deprecation")
Builder(RestContext context) {
- ClassInfo ci = ClassInfo.of(context.getResource().getClass());
+ ClassInfo ci = ClassInfo.of(context.getResource()).resolved();
for (RestResource r : ci.getAnnotationsParentFirst(RestResource.class)) {
if (! r.siteName().isEmpty())
siteName = r.siteName();
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
index fc26c55..2b353f5 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
@@ -3574,7 +3574,7 @@
VarResolverSession vrs = this.varResolver.createSession();
config = builder.config.resolving(vrs);
- ClassInfo rci = ClassInfo.of(resource);
+ ClassInfo rci = ClassInfo.of(resource).resolved();
PropertyStore ps = getPropertyStore();
@@ -3664,7 +3664,7 @@
ClasspathResourceFinder rf = getInstanceProperty(REST_classpathResourceFinder, ClasspathResourceFinder.class, ClasspathResourceFinderBasic.class, resourceResolver, this);
useClasspathResourceCaching = getProperty(REST_useClasspathResourceCaching, boolean.class, true);
- staticResourceManager = new ClasspathResourceManager(rci.getProxiedClass(), rf, useClasspathResourceCaching);
+ staticResourceManager = new ClasspathResourceManager(rci.inner(), rf, useClasspathResourceCaching);
consumes = getListProperty(REST_consumes, MediaType.class, parsers.getSupportedMediaTypes());
produces = getListProperty(REST_produces, MediaType.class, serializers.getSupportedMediaTypes());
@@ -3681,11 +3681,11 @@
MessageBundleLocation[] mbl = getInstanceArrayProperty(REST_messages, MessageBundleLocation.class, new MessageBundleLocation[0]);
if (mbl.length == 0)
- msgs = new MessageBundle(rci.getProxiedClass(), "");
+ msgs = new MessageBundle(rci.inner(), "");
else {
- msgs = new MessageBundle(mbl[0] != null ? mbl[0].baseClass : rci.getProxiedClass(), mbl[0].bundlePath);
+ msgs = new MessageBundle(mbl[0] != null ? mbl[0].baseClass : rci.inner(), mbl[0].bundlePath);
for (int i = 1; i < mbl.length; i++)
- msgs.addSearchPath(mbl[i] != null ? mbl[i].baseClass : rci.getProxiedClass(), mbl[i].bundlePath);
+ msgs.addSearchPath(mbl[i] != null ? mbl[i].baseClass : rci.inner(), mbl[i].bundlePath);
}
this.fullPath = (builder.parentContext == null ? "" : (builder.parentContext.fullPath + '/')) + builder.getPath();
@@ -3728,7 +3728,7 @@
methodsFound.add(mi.getSimpleName() + "," + emptyIfNull(firstNonEmpty(a.name(), a.method())) + "," + fixMethodPath(a.path()));
try {
if (mi.isNotPublic())
- throw new RestServletException("@RestMethod method {0}.{1} must be defined as public.", rci.getProxiedClass().getName(), mi.getSimpleName());
+ throw new RestServletException("@RestMethod method {0}.{1} must be defined as public.", rci.inner().getName(), mi.getSimpleName());
RestMethodContextBuilder rmcb = new RestMethodContextBuilder(resource, mi.inner(), this);
RestMethodContext sm = new RestMethodContext(rmcb);
@@ -3801,7 +3801,7 @@
addToRouter(routers, httpMethod, sm);
}
} catch (Throwable e) {
- throw new RestServletException("Problem occurred trying to serialize methods on class {0}, methods={1}", rci.getProxiedClass().getName(), SimpleJsonSerializer.DEFAULT.serialize(methodsFound)).initCause(e);
+ throw new RestServletException("Problem occurred trying to serialize methods on class {0}, methods={1}", rci.inner().getName(), SimpleJsonSerializer.DEFAULT.serialize(methodsFound)).initCause(e);
}
}
}
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
index a755bd3..20c8871 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
@@ -212,7 +212,7 @@
*/
RestContextBuilder init(Object resource) throws ServletException {
this.resource = resource;
- ClassInfo rci = ClassInfo.of(resourceClass);
+ ClassInfo rci = ClassInfo.of(resource).resolved();
Map<String,MethodInfo> map = new LinkedHashMap<>();
for (MethodInfo m : rci.getAllMethodsParentFirst()) {
diff --git a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java
index a24d9a6..1d2f4fb 100644
--- a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java
+++ b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerGenerator.java
@@ -102,7 +102,7 @@
@SuppressWarnings("deprecation")
public Swagger getSwagger() throws Exception {
- ClassInfo rci = ClassInfo.of(resource.getClass());
+ ClassInfo rci = ClassInfo.of(resource).resolved();
rci.getSimpleName();