teamcarma / swagger-jaxrs-doclet

This fork is no longer actively maintained, please switch to https://github.com/conorroche/swagger-doclet
Apache License 2.0
81 stars 38 forks source link

Doclet enters infinite loop when generic class parameter cannot be concretized #45

Closed alexradzin closed 9 years ago

alexradzin commented 9 years ago

In some cases ServiceDoclet got stuck. Debugging helps to locate the point where code cannot exit the endless loop:

public class ParserHelper {
       ..................................
    public static Type getVarType(TypeVariable var, Map<String, Type> varsToTypes) {
        Type res = null;
        if (var != null && varsToTypes != null) {
            Type type = varsToTypes.get(var.qualifiedTypeName());
            while (type != null) {
                res = type;
                type = varsToTypes.get(type.qualifiedTypeName());
            }
        }
        return res;
    }
      ..................................
}

The while() loop never exits.

Although I do not have SSCCE I will give a simplified version of my API that causes this problem.

My API looks like:

@Service
@Path("/measurements")
@Produces(APPLICATION_JSON)
@Consumes(APPLICATION_JSON)
public class MeasurementsService {
        .......................................
    @Path("/query") @POST
    public <G> MeasurementsResult<G> fetchMeasurements(MeasurementsQuery<G> query) {
        return callImpl(query);
    }
}

The class MeasurementsQuery has a lot of fields including AggregationGroupExtractor extractor parameterized on G too. This AggregationGroupExtractor is a interface that has several concrete implementations and declares one method:

public interface AggregationGroupExtractor<G> {
    G getGroup(MeasurementAggregation aggregation);
}

When I run javadoc with ServiceDoclet the method ParserHelper.getVarType() is called with varsToTypes that contains map like the following:

{T=java.lang.Integer, G=G}

Where

Mapping of G to G causes infinite loop because type is never null: it is always G.

My suggestion is to fix the while() condition as following:

while (type != null && !type.equals(res))

In this case the loop terminates when generic parameter is mapped to itself. This solution however does not solve longer chains (when A is mapped to B, B to C and C back to A), but I do not know whether such situation is possible.

conorroche commented 9 years ago

Thanks for the detailed bug report Alex, I will take a look at this over the next couple of days

alexradzin commented 9 years ago

I'll be glad to get update. So far I will try to continue with my, patched version.

conorroche commented 9 years ago

@alexradzin I was able to reproduce this based on your description and have added a test case for this and a fix, my fix should handle longer chains.

conorroche commented 9 years ago

@alexradzin can you confirm this fix works for you?

alexradzin commented 9 years ago

@conorroche, I have validated your fix. It words for me. When are yo planning to make this version available in maven repository? Right now I am going to use our local Artifactory but will be glad to work with official version.

conorroche commented 9 years ago

I hope to release 1.0.4 in the next couple of weeks, there are a couple of open issues id like to include in that release, i have been swamped with work recently but will see how it goes

conorroche commented 9 years ago

@alexradzin this is part of 1.0.4 which ive just release.