Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package io.swagger.jaxrs;

import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.type.TypeFactory;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiParam;
import io.swagger.converter.ModelConverters;
Expand Down Expand Up @@ -41,7 +39,6 @@ public static Parameter applyAnnotations(Swagger swagger, Parameter parameter, T
return null;
}
final String defaultValue = helper.getDefaultValue();
final JavaType javaType = TypeFactory.defaultInstance().constructType(type);
if (parameter instanceof AbstractSerializableParameter) {
final AbstractSerializableParameter<?> p = (AbstractSerializableParameter<?>) parameter;

Expand Down Expand Up @@ -112,14 +109,14 @@ public static Parameter applyAnnotations(Swagger swagger, Parameter parameter, T
bp.setAccess(param.getAccess());
}

final Property property = ModelConverters.getInstance().readAsProperty(javaType);
final Property property = ModelConverters.getInstance().readAsProperty(type);
if (property != null) {
final Map<PropertyBuilder.PropertyId, Object> args = new EnumMap<PropertyBuilder.PropertyId, Object>(PropertyBuilder.PropertyId.class);
if (StringUtils.isNotEmpty(defaultValue)) {
args.put(PropertyBuilder.PropertyId.DEFAULT, defaultValue);
}
bp.setSchema(PropertyBuilder.toModel(PropertyBuilder.merge(property, args)));
for (Map.Entry<String, Model> entry : ModelConverters.getInstance().readAll(javaType).entrySet()) {
for (Map.Entry<String, Model> entry : ModelConverters.getInstance().readAll(type).entrySet()) {
swagger.addDefinition(entry.getKey(), entry.getValue());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ protected Swagger read(Class<?> cls, String parentPath, String parentMethod, boo

Operation operation = null;
if(apiOperation != null || config.isScanAllResources() || httpMethod != null || methodPath != null) {
operation = parseMethod(method, globalParameters);
operation = parseMethod(cls, method, globalParameters);
}
if (operation == null) {
continue;
Expand Down Expand Up @@ -688,10 +688,10 @@ private Map<String, Property> parseResponseHeaders(ResponseHeader[] headers) {
}

public Operation parseMethod(Method method) {
return parseMethod(method, Collections.<Parameter>emptyList());
return parseMethod(method.getDeclaringClass(), method, Collections.<Parameter>emptyList());
}

private Operation parseMethod(Method method, List<Parameter> globalParameters) {
private Operation parseMethod(Class<?> cls, Method method, List<Parameter> globalParameters) {
Operation operation = new Operation();

ApiOperation apiOperation = getAnnotation(method, ApiOperation.class);
Expand Down Expand Up @@ -834,7 +834,7 @@ private Operation parseMethod(Method method, List<Parameter> globalParameters) {
Type[] genericParameterTypes = method.getGenericParameterTypes();
Annotation[][] paramAnnotations = method.getParameterAnnotations();
for (int i = 0; i < genericParameterTypes.length; i++) {
Type type = genericParameterTypes[i];
final Type type = TypeFactory.defaultInstance().constructType(genericParameterTypes[i], cls);
List<Parameter> parameters = getParameters(type, Arrays.asList(paramAnnotations[i]));

for (Parameter parameter : parameters) {
Expand Down Expand Up @@ -871,7 +871,6 @@ private List<Parameter> getParameters(Type type, List<Annotation> annotations) {
LOGGER.debug("trying extension " + extension);

final List<Parameter> parameters = extension.extractParameters(annotations, type, typesToSkip, chain);

if (parameters.size() > 0) {
final List<Parameter> processed = new ArrayList<Parameter>(parameters.size());
for (Parameter parameter : parameters) {
Expand Down
17 changes: 17 additions & 0 deletions modules/swagger-jaxrs/src/test/java/io/swagger/GenericsTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.google.common.collect.Sets;
import io.swagger.jaxrs.Reader;
import io.swagger.models.ArrayModel;
import io.swagger.models.Model;
import io.swagger.models.Operation;
import io.swagger.models.RefModel;
import io.swagger.models.Swagger;
Expand All @@ -17,14 +18,18 @@
import io.swagger.models.properties.StringProperty;
import io.swagger.models.properties.UUIDProperty;
import io.swagger.resources.ResourceWithGenerics;
import io.swagger.resources.generics.UserApiRoute;

import org.testng.annotations.Test;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;

public class GenericsTest {
Expand Down Expand Up @@ -211,4 +216,16 @@ public void checkGenericResult() {
assertEquals(items.getClass().getName(), RefProperty.class.getName());
assertEquals(((RefProperty) items).getSimpleRef(), "Tag");
}

@Test(description = "scan model with Generic Type")
public void scanModelWithGenericType() {
final Swagger swagger = new Reader(new Swagger()).read(UserApiRoute.class);
assertNotNull(swagger);
final Model userEntity = swagger.getDefinitions().get("UserEntity");
assertNotNull(userEntity);
final Map<String, Property> properties = userEntity.getProperties();
assertEquals(properties.size(), 2);
assertNotNull(properties.get("id"));
assertNotNull(properties.get("name"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package io.swagger.resources.generics;

import java.io.Serializable;

public abstract class AbstractEntity implements Serializable {
public String id;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package io.swagger.resources.generics;

import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.models.Response;

import java.util.List;

import javax.ws.rs.POST;

public abstract class ApiCrudRoute<T extends AbstractEntity> {
protected List<T> service;

@POST
@ApiOperation(value = "Create")
public Response doCreate(
@ApiParam(value = "Create object", required = true) T entity) throws Exception {
service.add(entity);
return new Response();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.swagger.resources.generics;

import io.swagger.annotations.Api;

import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/api/users")
@Api(value = "/users")
@Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
public class UserApiRoute extends ApiCrudRoute<UserEntity> {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.swagger.resources.generics;

import io.swagger.annotations.ApiModel;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
@ApiModel(value = "UserEntity")
@XmlAccessorType(XmlAccessType.FIELD)
public class UserEntity extends AbstractEntity {
public String name;
}