How to set Swagger UI's queryConfigEnabled parameter with Apache CXF?

Viewed 184

We are using Apache CXF for Swagger in our webapp (deployed in Tomcat) to display REST endpoints of our application. Everything is configured and is working perfectly until we upgraded Swagger UI from 3.52.5 to version 4.x.x. With Swagger UI version 4.x.x we always get the default Petstore API. I found that the reason for this is https://github.com/swagger-api/swagger-ui/issues/7702 We use the url parameter, which is getting ignored as reading config params from URL is disabled for security reasons. URL we use: http://host:port/webappname/doc/api-docs?url=/webappname/doc/openapi.json#/

I am trying to enable reading config params from URL by setting the queryConfigEnabled parameter to true but it's not working for me (I understand that there are security concerns). I found this page (https://cwiki.apache.org/confluence/display/CXF20DOC/OpenApiFeature) very close to what I am looking for but I couldn't locate any example on how to set queryConfigEnabled for the swaggerUiConfig property in my web.xml. Could someone please help me by providing examples of how to set this?

Sample web.xml:

  <servlet>
    <servlet-name>MyServlet</servlet-name>
    <servlet-class>
          org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet
    </servlet-class>
    <init-param>
      <param-name>javax.ws.rs.Application</param-name>
      <param-value>com.abc.xyz.MyApp</param-value>
    </init-param>
    <init-param>
        <param-name>redirects-list</param-name>
        <param-value>
        .*\.jsp
        .*\.jspx
        </param-value>
    </init-param>
    <init-param>
        <param-name>redirect-servlet-name</param-name>
        <param-value>mvc-dispatch</param-value>
    </init-param>
    <init-param>
        <param-name>static-resources-list</param-name>
        <param-value>
        /index.html
        .*\.html
        .*\.htm
        .*\.json
        .*\.js
        </param-value>
    </init-param>
    <init-param>
      <param-name>static-welcome-file</param-name>
      <param-value>/index.html</param-value>
    </init-param> 
    <load-on-startup>1</load-on-startup>
  </servlet>
  
  <servlet>
        <display-name>REST API Documentation</display-name>
        <servlet-name>RestAPIDoc</servlet-name>
        <servlet-class>org.apache.cxf.jaxrs.servlet.CXFNonSpringJaxrsServlet</servlet-class>
        <init-param>
            <param-name>jaxrs.serviceClasses</param-name>
            <param-value>com.abc.xyz.AgentManagerService</param-value>
        </init-param>
        <init-param>
            <param-name>jaxrs.features</param-name>
            <param-value>org.apache.cxf.jaxrs.openapi.OpenApiFeature</param-value>
        </init-param>
        <init-param>
            <param-name>jaxrs.providers</param-name>
            <param-value>
                org.apache.cxf.jaxrs.provider.MultipartProvider,
                com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider
            </param-value>
        </init-param>
                <load-on-startup>1</load-on-startup>
    </servlet>
    
    <servlet-mapping>
        <servlet-name>RestAPIDoc</servlet-name>
        <url-pattern>/doc/*</url-pattern>
    </servlet-mapping>

MyApp class:

public class MyApp extends Application {
    private Set<Object> singletons = new HashSet<Object>();
    private Set<Class<?>> classes = new HashSet<Class<?>>();

    public MyApp() throws ServletException {
        try {
            
            singletons.add(new JSONProvider());
            singletons.add(new WARProvider());

            Context m_context = getNamingContext();
            
            /* WS-Implementation for REST Transport Management */
            RestTransportManagerService restTransportManagerService = new RestTransportManagerService(m_context);
            singletons.add(restTransportManagerService);

            /* WS-Implementation for SOAP Transport Management */
            SoapTransportManagerService soapTransportManagerService = new SoapTransportManagerService(m_context);
            singletons.add(soapTransportManagerService);

            /* Added few more services in this way */

            AgentManagerService agentManagerService = new AgentManagerService();
            singletons.add(agentManagerService);

        }
        catch (Exception e) {
            String errorMessage = e.getMessage();
            ResponseBuilderImpl errorResponse =  new ResponseBuilderImpl();
            errorResponse.status(Response.Status.INTERNAL_SERVER_ERROR);
            errorResponse.entity(errorMessage);
            throw new ServletException(e.getMessage());
        }
    }

    private Context getNamingContext() throws NamingException{
        Context m_context = new InitialContext();
        NamingContext envContext = (NamingContext)m_context.lookup("java:comp/env");
        return m_context;
    }

    @Override
    public Set<Class<?>> getClasses() {
        return classes;
    }

    @Override
    public Set<Object> getSingletons() {
        final OpenApiFeature feature = new OpenApiFeature(); 
        feature.setSwaggerUiConfig(
                new SwaggerUiConfig()
                    .url("/oemanager/doc/openapi.json") 
                    .queryConfigEnabled(true));
        singletons.add(feature);
        return singletons;
    }
}

Versions Used:
CXF: 3.5.1 (can upgrade to latest CXF if required (https://mvnrepository.com/artifact/org.apache.cxf/cxf-core)
Swagger UI: 4.13.2 (Open for any version in 4 series (https://mvnrepository.com/artifact/org.webjars/swagger-ui)
JDK: openjdk version "17.0.3"
Platform: Windows
Container: Tomcat 9.0.64

1 Answers

You cannot set queryConfigEnabled for the swaggerUiConfig property in web.xml directly, but since you are using JAX-RS application instance com.abc.xyz.MyApp, the simplest way would be to include it into getSingletons() method:

class com.abc.xyz.MyApp extends Application {
    @Override
    public Set<Object> getSingletons() {
        final OpenApiFeature feature = new OpenApiFeature();
        
        feature.setSwaggerUiConfig(
            new SwaggerUiConfig()
                .url("/api-docs/openapi.json") /* please change that */
                .queryConfigEnabled(true));

        return Collections.singleton(feature);
    }
}

Hope it helps.

Related