'How to load all the examples in to the @ExampleObject without specifying the ref so its visible in SwaggerUI?

I am developing a simple application where I would like to read the files from a remote URL and add them to the @ExampleObject. I am able to achieve this using CustomClass SchemaFileReader implements OASFilter but the only problem is that I need to manually specify the name of the file in the ref such as @ExampleObject(name = "Example1", ref = "Example1.json").

Since I am reading the URL there can be many files and I do not know the name of all the files so I need an approach where I can add the @ExampleObject dynamically directly without specifying ref. Rather it should read all the data from the examples. Can someone please specify some logic on how to achieve this?

I have posted my complete code on GitHub: https://github.com/Aravinda93/code-with-quarkus.

As of now, I have added manually 2 files to my @ExampleObject by specifying the ref but I need a dynamic approach to add all the 3 files present in the resourses/jsonfiles without providing the ref for all the files individually.

To run the application, please follow the following steps:

  1. Open the terminal for the project and run mvn compile quarkus:dev
  2. Press d in the command line this should open the Swagger-UI.
  3. Select swagger-ui from SmallRye OpenAPI
  4. Expand api/generate and there we will see only 2 files under examples. I need an approach to get all 3 field without specifying the ref for all of them.


Solution 1:[1]

After trying some things, finally, this worked for me. Posting here as it can be useful to someone in the future:

Following is my RestControllerResponse:

import org.eclipse.microprofile.openapi.annotations.media.Content;
import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.util.Map;

@Path("/api")
public class RestControllerResponse {

    @Path("/generate")
    @POST
    @Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
    @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
    @RequestBody(description = "Testing Example without ref",
            content = @Content())
    public String generator(final Map<String, Object> input) throws Exception {
        return "Hello From Generator Method";
    }
}

Following is my SchemaFileReader which has the capability to read all files and respective subfolder with files and get the file contents and add to examples, pass the required URL to the getFolderData method:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.eclipse.microprofile.openapi.OASFactory;
import org.eclipse.microprofile.openapi.OASFilter;
import org.eclipse.microprofile.openapi.models.Components;
import org.eclipse.microprofile.openapi.models.OpenAPI;
import org.eclipse.microprofile.openapi.models.examples.Example;
import org.json.JSONArray;
import org.json.JSONObject;

import javax.ws.rs.core.MediaType;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

public class SchemaFileReader implements OASFilter {

    private final ObjectMapper objectMapper = new ObjectMapper();
    private final CloseableHttpClient httpClient = HttpClients.createDefault();

    @Override
    public void filterOpenAPI(OpenAPI openAPI) {

        Components defaultComponents = OASFactory.createComponents();
        if (openAPI.getComponents() == null) {
            openAPI.setComponents(defaultComponents);
        }

        try {
            //generateExamples().forEach(openAPI.getComponents()::addExample);
            generateExamples().entrySet().forEach(ex -> openAPI.getPaths().getPathItem("/api/generate").getPOST().getRequestBody().getContent().getMediaType(MediaType.APPLICATION_JSON).addExample(ex.getKey(), ex.getValue()));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    Map<String, Example> generateExamples() throws Exception {
        final Map<String, Example> examples = new LinkedHashMap<>();
        getFolderData(examples, "PLACE YOUR URL HERE");
        //getExamples(examples);
        return examples;
    }

    //If user has provided the folder then recursively loop over it to get the files and their contents
    private void getFolderData(final Map<String, Example> examples, final String inputURL) throws IOException {
        //Make the request to provided folder path and get the folder/files from it.
        final CloseableHttpResponse folderResponse = httpClient.execute(new HttpGet(inputURL));
        final String responseBody = EntityUtils.toString(folderResponse.getEntity(), StandardCharsets.UTF_8);

        //If the folder API request provides valid response and contains the list of files or folders then loop over it else its plain/text with direct contents
        if (folderResponse.getStatusLine().getStatusCode() == 200 && ContentType.get(folderResponse.getEntity()).toString().equalsIgnoreCase("application/json; charset=utf-8")) {

            final JSONArray jsonArray = new JSONArray(responseBody);

            jsonArray.forEach(item -> {
                final JSONObject obj = (JSONObject) item;

                if (obj.getString("type").equalsIgnoreCase("file")) {
                    //Make request to each file in the GitHub folder and obtain its contents
                    try {
                        final CloseableHttpResponse fileResponse = httpClient.execute(new HttpGet(obj.getString("download_url")));
                        //If the response code is 200 then add the contents to Example
                        if (fileResponse.getStatusLine().getStatusCode() == 200) {
                            final String fileResponseBody = EntityUtils.toString(fileResponse.getEntity(), StandardCharsets.UTF_8);
                            if (obj.getString("download_url").contains(".json")) {
                                examples.put(obj.getString("name"), OASFactory.createExample().value(objectMapper.readValue(fileResponseBody, ObjectNode.class)));
                            } else if (obj.getString("download_url").contains(".xml")) {
                                examples.put(obj.getString("name"), OASFactory.createExample().value(fileResponseBody));
                            }
                        }
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                } else {
                    try {
                        getFolderData(examples, obj.getString("url"));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            });

        } else if (folderResponse.getStatusLine().getStatusCode() == 200 && ContentType.get(folderResponse.getEntity()).toString().equalsIgnoreCase("text/plain; charset=utf-8")) {
            //if direct file provided then add its content
            examples.put(inputURL.substring(inputURL.lastIndexOf("/")), OASFactory.createExample().value(objectMapper.readValue(responseBody, ObjectNode.class)));
        }
    }
}


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 BATMAN_2008