Uploaded image for project: 'CXF'
  1. CXF
  2. CXF-7092

Swagger2Feature tries to resolve swagger-ui resources with api-docs

Details

    • Bug
    • Status: Closed
    • Minor
    • Resolution: Fixed
    • 3.1.7
    • 3.1.9, 3.2.0
    • JAX-RS
    • None
    • Spring Boot 1.4.1
      Swagger 2.2.2

    • Unknown

    Description

      Add Swagger2Feature for customization to the class annotated with @SpringBootApplication, e.g.:

         @Bean
         public Swagger2Feature swagger2Feature() {
            Swagger2Feature swagger2Feature = new Swagger2Feature();
            swagger2Feature.setPrettyPrint(true);
            swagger2Feature.setContact("person who knows the API");
      
            return swagger2Feature;
         }
      

      Open url for swagger UI in browser will fail with:

      Caused by: java.io.FileNotFoundException: JAR entry META-INF/resources/webjars/swagger-ui/2.2.2/api-docs/lib/swagger-oauth.js not found in /work/m2repository/org/webjars/swagger-ui/2.2.2/swagger-ui-2.2.2.jar
      	at sun.net.www.protocol.jar.JarURLConnection.connect(JarURLConnection.java:142)
      	at sun.net.www.protocol.jar.JarURLConnection.getInputStream(JarURLConnection.java:150)
      	at java.net.URL.openStream(URL.java:1045)
      	at org.apache.cxf.jaxrs.swagger.Swagger2Feature$SwaggerUIService.getResource(Swagger2Feature.java:298)
      	... 102 more
      

      Please note that it works correctly when the Swagger2Feature is auto-configured without customizations.

      Attachments

        1. cxf7092.png
          40 kB
          Sergey Beryozkin

        Activity

          Hi, how do you prepare Swagger UI and what URI do you use ?

          FYI, in CXF 3.1.7 Swagger2Feature auto-links to SwaggerUI. I've just tried a CXF spring_boot_scan demo on the master (3.2.0-SNAPSHOT), I've disabled the Swagger2Feature auto-discovery and added your code snippet, and could access Swagger UI as per the demo instructions.

          By the way, there were few additional fixes in CXF 3.1.8, it will be released very shortly, it is available at
          https://repository.apache.org/content/repositories/orgapachecxf-1081/

          right now, can you try it ?

          thanks, Sergey

          sergey_beryozkin Sergey Beryozkin added a comment - Hi, how do you prepare Swagger UI and what URI do you use ? FYI, in CXF 3.1.7 Swagger2Feature auto-links to SwaggerUI. I've just tried a CXF spring_boot_scan demo on the master (3.2.0-SNAPSHOT), I've disabled the Swagger2Feature auto-discovery and added your code snippet, and could access Swagger UI as per the demo instructions. By the way, there were few additional fixes in CXF 3.1.8, it will be released very shortly, it is available at https://repository.apache.org/content/repositories/orgapachecxf-1081/ right now, can you try it ? thanks, Sergey

          See the attached image

          sergey_beryozkin Sergey Beryozkin added a comment - See the attached image

          Hi Sergey, thx for the fast response. Just tried with 3.1.8, the issues still exists.

          I'm exactly using the auto-link feature as described in http://cxf.apache.org/docs/swagger2feature.html#Swagger2Feature-AutomaticUIActivation and accessing the UI using: http://localhost:8080/services/api-docs?url=/services/swagger.json

          In comparison with the demo you mentioned neither server.servlet-path, nor cxf.path and service-list-path are set in application.yml, everything relies on the default values.

          Unfortunately I cannot start this demo on master branch, it currently fails with:

          Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.apache.cxf.jaxrs.swagger.Swagger2Feature$ServletConfigProvider]: No default constructor found; nested exception is java.lang.NoSuchMethodException: org.apache.cxf.jaxrs.swagger.Swagger2Feature$ServletConfigProvider.<init>()
          	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:85)
          	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1098)
          	... 38 more
          Caused by: java.lang.NoSuchMethodException: org.apache.cxf.jaxrs.swagger.Swagger2Feature$ServletConfigProvider.<init>()
          	at java.lang.Class.getConstructor0(Class.java:3082)
          	at java.lang.Class.getDeclaredConstructor(Class.java:2178)
          	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:80)
          	... 39 more
          
          deki Dennis Kieselhorst added a comment - Hi Sergey, thx for the fast response. Just tried with 3.1.8, the issues still exists. I'm exactly using the auto-link feature as described in http://cxf.apache.org/docs/swagger2feature.html#Swagger2Feature-AutomaticUIActivation and accessing the UI using: http://localhost:8080/services/api-docs?url=/services/swagger.json In comparison with the demo you mentioned neither server.servlet-path, nor cxf.path and service-list-path are set in application.yml, everything relies on the default values. Unfortunately I cannot start this demo on master branch, it currently fails with: Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.apache.cxf.jaxrs.swagger.Swagger2Feature$ServletConfigProvider]: No default constructor found; nested exception is java.lang.NoSuchMethodException: org.apache.cxf.jaxrs.swagger.Swagger2Feature$ServletConfigProvider.<init>() at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:85) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1098) ... 38 more Caused by: java.lang.NoSuchMethodException: org.apache.cxf.jaxrs.swagger.Swagger2Feature$ServletConfigProvider.<init>() at java.lang.Class.getConstructor0(Class.java:3082) at java.lang.Class.getDeclaredConstructor(Class.java:2178) at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:80) ... 39 more

          Hi Dennis

          I've committed a fix for it - there was a JAX-RS Provider annotation on this private static class and I don't understand why but it was auto-discovered. If you remove a "classes-scan-packages: org.apache.cxf.jaxrs.swagger" property in application.yml then the demo will start OK - it has to be removed anyway to have a custom @Bean Swagger2Feature not duplicated (and I guess in all the real cases users would want to set Swagger2Feature properties anyway).
          Can you try without this property please ?

          thanks

          sergey_beryozkin Sergey Beryozkin added a comment - Hi Dennis I've committed a fix for it - there was a JAX-RS Provider annotation on this private static class and I don't understand why but it was auto-discovered. If you remove a "classes-scan-packages: org.apache.cxf.jaxrs.swagger" property in application.yml then the demo will start OK - it has to be removed anyway to have a custom @Bean Swagger2Feature not duplicated (and I guess in all the real cases users would want to set Swagger2Feature properties anyway). Can you try without this property please ? thanks

          I'm seeing this on the master too - I'm 100% sure I was running this demo without any problems, but I recall now the other fix involving this private class came in later on (to address a swagger docs for multiple endpoints issue)

          sergey_beryozkin Sergey Beryozkin added a comment - I'm seeing this on the master too - I'm 100% sure I was running this demo without any problems, but I recall now the other fix involving this private class came in later on (to address a swagger docs for multiple endpoints issue)

          I've tried this demo without the custom cxf.path and the services list path, and I still see Swagger2 JSON returned from "http://localhost:8080/services/api-docs?url=/services/swagger.json". Have a look please if you can reproduce it with the demo, or create a test project and we'll fix it.

          Sergey

          sergey_beryozkin Sergey Beryozkin added a comment - I've tried this demo without the custom cxf.path and the services list path, and I still see Swagger2 JSON returned from "http://localhost:8080/services/api-docs?url=/services/swagger.json". Have a look please if you can reproduce it with the demo, or create a test project and we'll fix it. Sergey

          With your fix the demo now boots up again, but accessing SwaggerUI fails with:

          Caused by: java.lang.NoSuchMethodError: javax.ws.rs.ClientErrorException.validate(Ljavax/ws/rs/core/Response;Ljavax/ws/rs/core/Response$Status$Family;)Ljavax/ws/rs/core/Response;
          	at javax.ws.rs.ClientErrorException.<init>(ClientErrorException.java:145) ~[javax.ws.rs-api-2.1-m01.jar:na]
          	at javax.ws.rs.NotFoundException.<init>(NotFoundException.java:104) ~[javax.ws.rs-api-2.1-m01.jar:na]
          	at org.apache.cxf.jaxrs.swagger.Swagger2Feature$SwaggerUIService.getResource(Swagger2Feature.java:441) ~[cxf-rt-rs-service-description-swagger-3.2.0-SNAPSHOT.jar:3.2.0.SNAPSHOT]
          	at sun.reflect.GeneratedMethodAccessor92.invoke(Unknown Source) ~[na:na]
          	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_101]
          	at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_101]
          	at org.apache.cxf.service.invoker.AbstractInvoker.performInvocation(AbstractInvoker.java:180) ~[cxf-core-3.2.0-SNAPSHOT.jar:3.2.0.SNAPSHOT]
          	at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:96) ~[cxf-core-3.2.0-SNAPSHOT.jar:3.2.0.SNAPSHOT]
          	... 63 common frames omitted
          

          You can check https://github.com/deki/cxf/tree/CXF-7092 for the changes I made.

          deki Dennis Kieselhorst added a comment - With your fix the demo now boots up again, but accessing SwaggerUI fails with: Caused by: java.lang.NoSuchMethodError: javax.ws.rs.ClientErrorException.validate(Ljavax/ws/rs/core/Response;Ljavax/ws/rs/core/Response$Status$Family;)Ljavax/ws/rs/core/Response; at javax.ws.rs.ClientErrorException.<init>(ClientErrorException.java:145) ~[javax.ws.rs-api-2.1-m01.jar:na] at javax.ws.rs.NotFoundException.<init>(NotFoundException.java:104) ~[javax.ws.rs-api-2.1-m01.jar:na] at org.apache.cxf.jaxrs.swagger.Swagger2Feature$SwaggerUIService.getResource(Swagger2Feature.java:441) ~[cxf-rt-rs-service-description-swagger-3.2.0-SNAPSHOT.jar:3.2.0.SNAPSHOT] at sun.reflect.GeneratedMethodAccessor92.invoke(Unknown Source) ~[na:na] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_101] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_101] at org.apache.cxf.service.invoker.AbstractInvoker.performInvocation(AbstractInvoker.java:180) ~[cxf-core-3.2.0-SNAPSHOT.jar:3.2.0.SNAPSHOT] at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:96) ~[cxf-core-3.2.0-SNAPSHOT.jar:3.2.0.SNAPSHOT] ... 63 common frames omitted You can check https://github.com/deki/cxf/tree/CXF-7092 for the changes I made.

          So the problem here is the scan-packages: org.apache.cxf.jaxrs.swagger". If it is present in addition to the @Bean Swagger2Feature it get messed up.

          I suggest to simply replace the one from scan-packages if it is manually configured.

          deki Dennis Kieselhorst added a comment - So the problem here is the scan-packages: org.apache.cxf.jaxrs.swagger". If it is present in addition to the @Bean Swagger2Feature it get messed up. I suggest to simply replace the one from scan-packages if it is manually configured.

          I've ended up adding a warning if the providers with the same class name have been detected.
          In most cases it is a sign of the configuration/setup issue, but besides that, even though @Component classes are only detected if they have been explicitly enabled via @Bean or in the application context resources, I've been thinking for a while to also support the class path scanning of @Component classes, Spring scanner does support it but it has not just been integrated into CXF and in that case it will be hard to decide what takes the priority if we can have say a JAX-RS provider which is also annotated as @Component.
          IMHO doing the warning is reasonable at this stage...
          thanks

          sergey_beryozkin Sergey Beryozkin added a comment - I've ended up adding a warning if the providers with the same class name have been detected. In most cases it is a sign of the configuration/setup issue, but besides that, even though @Component classes are only detected if they have been explicitly enabled via @Bean or in the application context resources, I've been thinking for a while to also support the class path scanning of @Component classes, Spring scanner does support it but it has not just been integrated into CXF and in that case it will be hard to decide what takes the priority if we can have say a JAX-RS provider which is also annotated as @Component. IMHO doing the warning is reasonable at this stage... thanks

          fine for me, a warning would have pointed me in the right direction...thx!

          deki Dennis Kieselhorst added a comment - fine for me, a warning would have pointed me in the right direction...thx!

          People

            sergey_beryozkin Sergey Beryozkin
            deki Dennis Kieselhorst
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: