-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Issue with generics model and return type #498
Comments
Just FYI, I made some changes to enable this. The change might be too big to merge into your development. There are basically two changes:
The change pass all unit tests. I added unit tests for ClassWrapper I didn't add a model test case to verify, but it worked well in my project. Now the APIs can return generic types:
Here are the commits. |
👍 |
Just wondering why this was closed? Will there be support for generic types for responses? |
It was never closed. |
support for generics is limited, but I believe this is going to be handled with the jackson mapper in 1.5.0 |
For now, there is the opportunity to override datatypes with the
where you override the datatype with whatever you like, which means generics can be expressed in any concrete class. |
Partial solution, moving to M2 for more investigation and more use cases. |
Will there be a general solution to this problem? I am exposing an API with a general "ResultList" implementation supporting paging: public class ListResult<T> {
public long size = 0;
public long rangeFrom = 0;
public long rangeSize = 0;
public List<T> entries = Collections.emptyList();
} And I should really have the |
It is technically impossible to support all forms of generics. The general solution is to manually map generics to an interface or type if runtime reflection is not possible. There will be guidelines for M2, which we're working on. |
I found a "reasonable" way for my case to give the correct output to work in swagger ui, by subclassing the return type and overriding the generic parts. Note that my private class is not used in code, only as parameter for swagger and the public class ListResult<T> {
public long size = 0;
public long rangeFrom = 0;
public long rangeSize = 0;
public List<T> entries = Collections.emptyList();
}
@Path("/records")
@Api(value = "/records", description = "")
public class RecordsResource {
@GET
@Path("inbox")
@ApiOperation(value = "/inbox", response = RecordResultList.class)
public Response inbox() {
ListResult<Record> result = ListResult.create(records, Record::new);
return Response.ok().entity(result).build();
}
private static class RecordResultList extends ListResult<Record> {
public List<Record> entries;
}
} Hope this helps somebody else, for me this works as an OK workaround. |
+1 |
Fixed #498: Handling of generic responses has been fixed.
It's impossible to pass generic type via the @GET
@Path("inbox")
@ApiOperation(value = "/inbox")
public ListResult<Record> inbox() {
return ListResult.create(records, Record::new);
} |
@tomtit - that would work only if the method returns the type itself. The more common use case with JAX-RS is to return a |
In this case the |
And then how would it be represented? |
Unfortunately there is no way to do this as JLS states:
|
So, we need to use the workaround with a non-generic type ( |
Not really up to us but up to the users, but sure, we're limited with our options. |
Why is this issue closed? Is there any new issue tracking this problem? @ovstetun 's workaround is fine, but it may cause too many classes to be created. |
@chenjianjx please see my comment #498 (comment) |
ok, thank you |
@fehguy sure you can not support ALL POSSIBLE forms of generic, however you can easily support at least very common patterns which can make life better. Just simple e.g. Result<T, U> and than have possibility to specify for example return type as Result<String,Person>. This is supported by many languages and doesn't require too much changes in spec. |
Which limitations? Erasures are in generic type (e.g. List), in concrete type you can find it easily. This code produce:
|
If you feel things can be improved, you're more than welcome to submit PRs with changes. |
@webron I'm still confused by spec. Maybe implementation is fine, I would like to have very simple Java return type like PagingResult:
And than AddressService.find method which return just PagingResult<Address>. What is correct way of specifying PagingResult in Swagger? Do I have to create specific type for each service? |
You'd need to create a specific type for each service, yes. OAI/OpenAPI-Specification#555 covers this as a feature request for the next version as there's no easy way to define wrappers for responses. |
Thanks @webron, I will track that issue. |
@tavoda actually it depends on the way you define your resource:
|
@tomtit nice to know, thanks |
Hey, guys! Maybe it will be usefull. I had same issues with my Spring based application and I've used alternate type rules in the Swagger config:
This means: Swagger, if you will find Here is a controller's method signature:
And now Swagger generates returned JSON description based on generic Have a nice day! PS for more info read http://springfox.github.io/springfox/docs/snapshot |
@Marvel77 thank you for sharing |
How is this solved? |
It's problem of SPEC. This mean is not possible to specify real generic return type. Core is handling it fine as mentioned by @tomtit . It should be closed. |
The reflection can't find proper generic model property.
The reflection can find the ResultList results property, but it shows as an array of objects. To work around, I have to override the methods:
The issue also exists in the method return types. I looked at the code and seems it's not trivial to make a fix. All reflection functions are expecting a
Class[_]
rather thanType
.The text was updated successfully, but these errors were encountered: