Skip to content
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

Cannot generate swagger.json when JAX-RS annotated endpoints comes from superclass #140

Open
afrunt opened this issue Nov 30, 2017 · 1 comment

Comments

@afrunt
Copy link

afrunt commented Nov 30, 2017

Cannot generate swagger.json when JAX-RS annotated endpoints comes from superclass.
This issue related to maven plugin (0.16). In case I extend generic abstract class with JAX-RS endpoints and do add any endpoint to actual resource, then I'm receiving empty endpoint in swagger.json.

{
    "swagger": "2.0",
    "info": {
        "version": "0.1",
        "title": "web"
    },
    "host": "",
    "basePath": "/web/api",
    "schemes": [
        "http"
    ],
    "paths": {
        "/news": {
            "get": {
                "consumes": [
                ],
                "produces": [
                ],
                "parameters": [
                ],
                "responses": {
                    "204": {
                        "description": "No Content",
                        "headers": {
                        }
                    }
                }
            }
        },
        "/news/some": {
            "post": {
                "consumes": [
                    "application/json"
                ],
                "produces": [
                    "application/json"
                ],
                "parameters": [
                ],
                "responses": {
                    "204": {
                        "description": "No Content",
                        "headers": {
                        }
                    }
                }
            }
        }
    },
    "definitions": {
    }
}

When I adding the endpoint to the actual resource implementation, its metadata exposed in swagger.json (like news/some at the above code snippet), but not the metadata of the endpoints from the parent abstract classes.
I will also try to debug the jaxrs-analyzer by myself.
Thanks!

@TristanPerry
Copy link

TristanPerry commented Nov 11, 2019

This issue is caused by the ASM library (used to analyze a class) not scanning super classes by design - hence ProjectAnalyzer.analyseClass() only returns that class' method results.

A general fix approach is to recursively visit any superclasses that exist (if a class has no extends ..., its superclass will be java/lang/Object):

    private void analyzeClass(final String className, ClassResult classResult) {
        try {
            final ClassReader classReader = new ContextClassReader(className);
            final ClassVisitor visitor = new JAXRSClassVisitor(classResult);

            classReader.accept(visitor, ClassReader.EXPAND_FRAMES);

            // recursively visit any super classes
            if (!classReader.getSuperName().equals("java/lang/Object")) {
                analyzeClass(classReader.getSuperName(), classResult);
            }
        } catch (IOException e) {
            LogProvider.error("The class " + className + " could not be loaded!");
            LogProvider.debug(e);
        }
    }

With the above approach, I was then seeing issues with the JavaDocs missing but the following fixed it for me - i.e. replace JavaDocAnalyzer.combineResults() with the below, and remove JavaDocAnalyzer.findMethodResult() completely:

    private void combineResults(final Set<ClassResult> classResults) {
        classResults.stream()
            .flatMap(classResult -> classResult.getMethods().stream()) // flatten our set of sets (multiple methods within multiple class results) into one set
            .forEach(methodResult -> {
                // For our single methodResult, see if we have a matching entry in the methodComments map (if we do, set the 'methodDoc' property)
                this.methodComments.entrySet().stream()
                    .filter(entry -> equalsSimpleTypeNames(entry.getKey(), methodResult))
                    .map(Entry::getValue)
                    .findAny()
                    .ifPresent(methodResult::setMethodDoc);
            });
    }

I'll look to submit a PR for this shortly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants