avaje / avaje-http

Controller generation for Javalin, Helidon SE.
https://avaje.io/http/
Apache License 2.0
71 stars 13 forks source link

Adding endpoint from other libs to openapi documentation #51

Open Tijs-2 opened 3 years ago

Tijs-2 commented 3 years ago

Hi Rob,

I was looking into a way to add endpoint from another lib to the openapi documentation of the final service.

For example I have a base project y that provides a general /health or /info endpoint and I use that lib in project z. The endpoints are made available with the use of your inject project when I start the application, but they are not present in the openapi documentation.

Now I was wondering and trying out but could not achieve this by looking for the "Controller" classes and trying to add them but it is not looking to other inherited projects.

Would something like this be possible in combination with the @ContextModule[depenson=project y] so we know where to look and then add those endpoints? Because it would be nice to add all available endpoints to the final documentation.

Kind regards, Tijs

rbygrave commented 3 years ago

My first thought is something like: Each module generates the swagger file with a unique name (e.g. health-openapi.json) and a properties resource that points to it's location (/openapi.location.properties with content like location=/health-openapi.json).

Then to "merge" the API's into a single API something could load all the /openapi.location.properties resources and hence then load all the module api json resources and then merge them.

Something like that. Hmmm.

Tijs-2 commented 3 years ago

Could be an idea bundling the openapi files, I should try it with 2 files. I have done a quick search but did not find a good library but will try again tomorror. Or trying to merge them just as json files...

I have also been checking if I can find the other controllers and maybe add them to the openapi processor from the io.avaje.http.generator.core.BaseProcessor but I cannot search other jar files.

Maybe it cannot be done or it is some knowledge that I lack, could also just be not a good way to go...

Tijs

PS, not really for this issue did you find some time to check my pull request because it would be nice to use it in my application

Tijs-2 commented 3 years ago

Hi @rbygrave

I have found a way but it is quite some workand do not know if you are interested in this. With a method of the org.reflections library I can find all the packages with a BeanContextFactory and within those packages the classes annotated with the right annotations.

Like this: List packages = new ArrayList<>(); for(URL url: ClasspathHelper.forClassLoader()) { Reflections reflection = new Reflections(new ConfigurationBuilder().setUrls(url).setScanners(new ResourcesScanner()));

  if(reflection.getResources(Pattern.compile(".*\\.BeanContextFactory")).size() > 0)
    packages.add(url);
}

Reflections reflection = new Reflections(new ConfigurationBuilder().setUrls(packages).setScanners(new SubTypesScanner(), new TypeAnnotationsScanner()));
try {
  for(Class taggedClasses: reflection.getTypesAnnotatedWith(Tag.class)) {
    ctx.doc().addTagDefinition((Tag)taggedClasses.getAnnotation(Tag.class));
  }

  for(Class taggedClasses: reflection.getTypesAnnotatedWith(Tags.class)) {
    ctx.doc().addTagsDefinition((Tags)taggedClasses.getAnnotation(Tags.class));
  }

  for(Class taggedClasses: reflection.getTypesAnnotatedWith(Controller.class)) {
    System.out.println(taggedClasses.toString());
    System.out.println(processingEnv.getElementUtils().getTypeElement(taggedClasses.toString()));
  }

But to actually process them I was looking into the code, and could not convert them into elements. I tried another way but it costs a lot of time so I would like to know if you would be interested in this because then I will try to find some more time to process the classes next to the Elements and Types

Tijs