Open nefsir opened 6 years ago
This issue is not exclusive to WebFlux/Reactor types. You will also have this issue with other wrapper types, like Spring web's DeferredResult
andResponseEntity
. Or Callable
, Future
or CompletableFuture
. Or RxJava's Single
, Observable
and Flowable
.
You can fix this issue in your project using a ModelConverter
like this (you can take out the entries for the classes you don't have in your project):
package your.nice.package;
import io.reactivex.Flowable;
import io.swagger.converter.ModelConverter;
import io.swagger.converter.ModelConverterContext;
import io.swagger.jackson.AbstractModelConverter;
import io.swagger.models.Model;
import io.swagger.models.properties.Property;
import io.swagger.util.Json;
import org.springframework.http.ResponseEntity;
import org.springframework.web.context.request.async.DeferredResult;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import rx.Observable;
import rx.Single;
import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;
public class UnwrappingModelConverter extends AbstractModelConverter {
private static final Set<Type> classesToUnwrap;
static {
final Set<Type> set = new HashSet<>();
// JDK
set.add(Callable.class);
set.add(CompletableFuture.class);
set.add(Future.class);
// Project Reactor
set.add(Mono.class);
set.add(Flux.class);
// Spring web
set.add(ResponseEntity.class);
set.add(DeferredResult.class);
// RxJava 1.x
set.add(Single.class);
set.add(Observable.class);
// RxJava 2.x
set.add(io.reactivex.Single.class);
set.add(io.reactivex.Observable.class);
set.add(Flowable.class);
classesToUnwrap = set;
}
public UnwrappingModelConverter() {
super(Json.mapper());
}
@Override
public Property resolveProperty(Type type, ModelConverterContext context, Annotation[] annotations, Iterator<ModelConverter> chain) {
return super.resolveProperty(unwrap(type), context, annotations, chain);
}
@Override
public Model resolve(Type type, ModelConverterContext context, Iterator<ModelConverter> chain) {
return super.resolve(unwrap(type), context, chain);
}
private Type unwrap(Type type) {
if (type instanceof ParameterizedType) {
final ParameterizedType parameterizedType = (ParameterizedType) type;
// Recursively unwrap
if (classesToUnwrap.contains(parameterizedType.getRawType())) {
return unwrap(parameterizedType.getActualTypeArguments()[0]);
}
}
return type;
}
}
Enable your model converter by creating src/main/resources/META-INF/services/io.swagger.converter.ModelConverter
and putting the fully qualified class name of your model converter in it.
I was testing this converter above and don't work.
Basically, even if the response is MonoType
is never a ParameterizedType
, all of the, are SimpleType
.
If I print the Type
it looks like the correct one.
For instance for a return type Mono<Something>
I have the bellow:
"definitions" : {
"Mono" : {
"type" : "object"
},
"MonoSomething" : {
"type" : "object"
}
}
Any idea?
I've faced some problems with swagger.yaml generation while migrating to Spring Webflux. When response type is wrapped in Mono than swagger.yaml doesn't contain wrapped type information.