Hi Jean, The main problem to configure Swagger property in your particular case is that the server address is not "known" or "introspectable" for Swagger. Intuitively, it has to be set manually using basePath to the, essentially, the server address part:
- /op/services/accounts - /op/services/resources - /op/services/dienstverlener You could read more about other Swagger properties you have asked here: https://github.com/swagger-api/swagger-core/wiki/Swagger-2.X---Integration-and-Configuration#configuration-properties You definitely need to set usePathBasedConfig to "true" otherwise you will see the same Swagger specs for all servers. We have a sample here which uses 2 jaxrs:server instances: https://github.com/apache/cxf/tree/3.6.x-fixes/distribution/src/main/release/samples/jax_rs/description_swagger2_web Regarding SwaggerUI, I think the value for each of those should be set to, respectively: - /op/services/accounts/swagger.yaml - /op/services/resources/swagger.yaml - /op/services/dienstverlener/swagger.yaml I believe this is matching your settings already, except the usePathBasedConfig part. The example referred above could be helpful, my apologies if I missed something, there are quite a lot of questions :-) The fact that the generated Swagger specification is empty is unexpected - it should not happen when JAX-RS resources are properly configured. Thank you. Best Regards, Andriy Redko JPU> RE: How to setup multiple JAXRS server endpoints JPU> Hi Andriy, JPU> I am not quite understanding how to correctly configure the Swagger2Feature. JPU> Referring to the attached cxf-endpoints configuration I (as a test) created JPU> 3 JAXRS server instances: JPU> 1. A* KmopApiServer* server for the* JPU> be.dvtm.aeo.op.sodexo.api.KmopApiService* interface, serving requests for JPU> URI path: JPU> * <protocol>**//<host:<port>/op/services/accounts* JPU> ‘op’ = root path of the web application JPU> ‘services’ = servlet path of the CXF-servlet JPU> The address of the server is set to ‘/accounts’ and the @Path(…) JPU> annotation on the interface class was cleared. JPU> 2. A* Kmop**Resources**ApiServer* server for the* be.dvtm.aeo.op.* JPU> *openapi.**api.Kmop**Recources**ApiService* interface, serving requests for JPU> URI path: JPU> * <protocol>**//<host:<port>/op/services/**resources* JPU> The address of the server is set to ‘/resources’ and the @Path(…) JPU> annotation on the interface class was cleared. JPU> 3. A* Kmop**Dienstverlener**Server* server for the* be.dvtm.aeo.op.* JPU> *openapi**.api.Kmop**Dienstverlener**Service* interface, serving requests JPU> for URI path: JPU> * <protocol>**//<host:<port>/op/services/**dienstverlener* JPU> The address of the server is set to ‘/dienstverlener’ and the @Path(…) JPU> annotation on the interface class was cleared. JPU> For each of these server instances I’ve set the Swagger2Feature with JPU> configuration as indicated in the attached cxf-endpoints.xml. JPU> With regard to the configurations for the Swagger2Feature I’ve the JPU> following questions: JPU> a) Referring to *https://cxf.apache.org/docs/swagger2feature.html* JPU> <https://cxf.apache.org/docs/swagger2feature.html> could you clarify on JPU> the following configuration parameters: JPU> *i. ** basePath* – Is this the path to the CXFServlet context (‘ JPU> /op/services’) or to the JAX-RS server instance (e.g. JPU> ‘/op/services/accounts’) or still something else? Is it used to resolve JPU> service classes or is it just for documentation in the swagger file? JPU> *ii. ** resourcePackage* – the description mentions ‘package names’ JPU> while the default mentions ‘service classes’? Service 2 and 3 above are JPU> within the same package (generated from the same yaml specification that JPU> included both interfaces). JPU> *iii. ** ig**noreRoutes* – is this taken into account when JPU> scanAllResources=false? JPU> *iv. ** swaggerUiConfig* – What is the correct ‘url’ parameter value JPU> (cf. question ‘a’)? JPU> b) What would be the correct URL to generate a swagger.yaml file for JPU> each of the above interfaces? Initially I called: JPU> *i. ** <protocol>**//<host:<port>/op/services/accounts**/swagger.yaml* JPU> *ii. ** <protocol>**//<host:<port>/op/services/**resources/swagger.yaml* JPU> *iii. ** <protocol>**//<host:<port>/op/services/**dienstver* JPU> *lener/swagger.yaml* JPU> All three requests delivered the same yaml specification, namely the one JPU> for interface* KmopApiServer*? JPU> c) I tried to debug the processing of the requests under ‘b)’ and this JPU> is done by the class JAXRSInterceptor#processRequest where the MessageImpl JPU> object for request “ii.” looks like the one attached. It finds 3 resource JPU> classes: JPU> be.dvtm.aeo.op.openapi.api.impl.KmopResourcesApiServiceImpl JPU> org.apache.cxf.jaxrs.swagger.Swagger2ApiListingResource JPU> org.apache.cxf.jaxrs.swagger.ui.SwaggerUiService JPU> è It matches the request to resource* Swagger2ApiListingResource* with JPU> UriInfo={type=[yaml], FINAL_MATCH_GROUP=[/]}} and calling its* process(…)* JPU> method. JPU> è Here it seems to go wrong. It generates a SwaggerContextService JPU> having basePath=/op/services/resources/,swaggerConfig=null, JPU> usePathBasedConfig=null and then calls SwaggerContextService.getSwagger() JPU> which returns the Swagger definition for interface KmopApiServer? It looks JPU> like it caches generated swagger definitions based on a configIdKey with JPU> prefix ’swagger.config.id.xxx’. This key is the same for all 3 interfaces JPU> as usePathBasedConfig=null JPU> and maps to ‘swagger.config.id.default’. The usePathBasedConfig is derived JPU> from the ServletConfig parameter ‘swagger.use.path.based.config’.* So JPU> should this be set on the declaration of the CXFServlet** in web.xml?* JPU> è Actually the SwaggerConfig, the JaxrsScanner and the generated Swagger JPU> are cached using keys like ‘swagger.config.id.[default|baseUriPath]’, ‘ JPU> scanner.config.id.[default|baseUriPath]’. Caching with ‘baseUriPath’ is JPU> only done when usePathBasedconfig=true. JPU> è If I patch this to true then configIdKey=’ JPU> swagger.config.id./op/services/resources/’ and no swagger entry is cached JPU> for this key so it will generate a new one. Again by patching JPU> SwaggerContextService.isUsePathBasedConfigInitParamDefined(sc)=true JPU> it will call: “swagger = scan(app, servletContext, sc, uriInfo);” JPU> è Again Scanners are cached and if usePathBasedConfig=null it will use JPU> the one cached under ‘swagger.scanner.id.default’ and this again returns JPU> the swagger definition for the KmopApiService interface. JPU> è So patching usePathBasedConfig=true will return a new one JPU> (DefaultJaxrsScanner). The classes to scan for in this new scanner are ‘ JPU> be.dvtm.aeo.op.openapi.api.impl.KmopResourcesApiServiceImpl‘ which is JPU> correct. It will generate a new (but empty) Swagger object. JPU> è Next Swagger2ApiListingResource will call the JPU> customizer.customize(s), which still isn’t putting anything new in the JPU> Swagger object. Should it or should the next step do this? JPU> è Next BaseApiListingResource#getListing(…) is called which on its JPU> turn calls getListingYamlResponse(..) JPU> è The final result is a swagger.yaml document with following content: JPU> swagger: "2.0" JPU> info: JPU> license: JPU> name: "Apache 2.0 License" JPU> url: http://www.apache.org/licenses/LICENSE-2.0.html JPU> basePath: "/op/services/resources" JPU> So basically an empty swagger file. JPU> d) The usePathBasedConfig is derived from the ServletConfig parameter ‘ JPU> swagger.use.path.based.config’. Without this parameter set to true there JPU> will be only one Swaggerconfig, JaxrsScanner and Swagger object.* So should JPU> this be set on the declaration of the CXFServlet** in web.xml?* JPU> The majority in this processing happens in the library swagger-jaxrs-v1.6.10 JPU> which is included as a dependency on cxf-rt-rs-service-description-swagger. JPU> Even if I patch usePathBasedConfig=true about everywhere where I met this JPU> it still doesn’t generate a correct swagger.yaml. Am I still missing some JPU> configuration parameter? JPU> Any suggestions on how to resolve this would be welcome. JPU> Regards, JPU> J.P. Urkens JPU> <<...>> <<...>> JPU> -----Original Message----- JPU> From: Andriy Redko <drr...@gmail.com> JPU> Sent: maandag 8 mei 2023 23:15 JPU> To: Jean Pierre URKENS <jean-pierre.urk...@devoteam.com>; CXF Dev List < dev@cxf.apache.org>> JPU> Subject: Re: How to setup multiple JAXRS server endpoints JPU> Hi Jean, JPU> Indeed the way you would like to do that is somewhat tricky. >> So I tried to keep the @Path declaration on the interface classes but JPU> changed them to @Path(“”). That does seems to work except the swagger stuff JPU> no longer correctly works. JPU> This is one of the possible options but OpenAPI/Swagger gets confused for a JPU> reason: the path is now implicit (not in the spec). JPU> So how about this option: JPU> - use only one JAX-RS server (address "/") JPU> - host both resources but use @Path("accounts") and @Path("resources") on JPU> them respectively JPU> I see that for @Path("accounts") you need to apply the JPU> "kmopApiAuthorizationFilter", that could be done using DynamicFeature [1], JPU> [2]. If this is not the option and you would prefer to use 2 separate JPU> JAX-RS servers, you may need to provide your own instance of JPU> Swagger2Customizer [3], [4] which allows to transform the OpenAPI/Swagger JPU> on the fly. Please let me know if that would it work for you, thank you. JPU> [1] JPU> https://docs.oracle.com/javaee/7/api/javax/ws/rs/container/DynamicFeature.html JPU> [2] JPU> https://aredko.blogspot.com/2016/02/your-jax-rs-apis-were-not-born-equal.html JPU> [3] JPU> https://cxf.apache.org/javadoc/latest/org/apache/cxf/jaxrs/swagger/Swagger2Customizer.html JPU> [4] https://cxf.apache.org/docs/swagger2feature.html (has customizer JPU> property) JPU> Best Regards, JPU> Andriy Redko >> Hi Andriy, >> I am again getting into trouble with server endpoint declarations. Now JPU> because I am adding additional JAX-RS endpoints. >> The issue is with: >> 1. The 'address' attribute on the <jaxrs:server> declaration in JPU> combination with >> 2. The 'url-pattern' for the CXFServlet declaration in the web.xml JPU> in combination with >> 3. The @Path declaration in the interface class in combination with >> 4. The @Path declaration on the interface method in combination with >> So what I had is that my web application deployed under baseUlr 'op' had JPU> one JAXRS server endpoint with declarations like: >> 1. <jaxrs:server id="restServer" JPU> basePackages="be.dvtm.aeo.op.sodexo" address="/"> >> 2. <url-pattern>/services/*</url-pattern> >> 3. @Path("accounts") on the public interface class >> 4. @Path("/{authorisationId}/customerFund") on the customerFund JPU> interface method >> A valid API call would thus be e.g.: >> https://<hostname>:<port>/op/services/accounts/{authorizationId}/custo >> merFund >> And this works correctly. >> We're now introducing additional JAX-RS service endpoints and now I am JPU> running into problems. This second endpoint was declared with: >> 1. <jaxrs:server id="resourceServer" JPU> basePackages="be.dvtm.aeo.op.resources" address="/"> >> 2. <url-pattern>/services/*</url-pattern> >> 3. @Path("resources") on the public interface class >> 4. @Path("/NACE") on the NACE interface method >> So here a valid API call woud be: JPU> https://<hostname>:<port>/op/services/resources/NACE. >> The problem is that I can not declare two <jaxrs:server> entries with the JPU> same ‘address’ as it throws the exception: >> Caused by: org.apache.cxf.service.factory.ServiceConstructionException: JPU> There is an endpoint already running on /. >> So I tried changing the addresses to: >> · address=”accounts” for the restServer >> · address=”resources” for the resourceServer >> But to keep the API-call URLs the same I removed the @Path declaration on JPU> the interface classes. By doing so the <jaxrs:server> bean declarations no JPU> longer loads successfully. >> So I tried to keep the @Path declaration on the interface classes but JPU> changed them to @Path(“”). That does seems to work except the swagger stuff JPU> no longer correctly works. >> So what is the decent way to setup multiple JAX-RS server endpoints where JPU> each server has its own configuration regarding supported features: >> · own validation >> · own object and exception mappings >> · own swagger file generation >> · own logging (in separate file if possible) >> I am using Apache CXF-3.5.2 which uses swagger-core v1.6.6 in cooperation JPU> with swager-ui v4.5.0. >> Below the declarations of my endpoints <<...>> Thanks for any advice. >> Regards, >> J.P. Urkens >> -----Original Message----- >> From: Andriy Redko <drr...@gmail.com> >> Sent: zaterdag 18 juni 2022 1:12 >> To: Jean Pierre URKENS <jean-pierre.urk...@devoteam.com>; >> iss...@cxf.apache.org; dev@cxf.apache.org >> Subject: Re: JAXRS server endpoint not gracefully shutdown Hi Jean, >>> 1. a jaxrs server on url: '/<basePath>/services/service1' >> Correct, so in the relative form like address="/<something>", the JAX-RS JPU> endpoint path would be: >> <baseUrl>/<servlet path >> mapping>/<address>/[@ApplicationPath]/[@Path] >> The @ApplicationPath is optional in this case. >>> 2. a jaxws service endpoint on '/<basePath>/services/service2' >> The JAX-WS is very different from JAX-RS, essentially the action comes JPU> inside the SOAP message behind <baseUrl>/<servlet path mapping>/ (@Path / JPU> @ApplicationPath are not relevant there). >>> Question: Because now address="/" is set for the jaxrs:server will it >>> also inspect requests targeted for the jaxws service as those >>> requests have start with the same path '/<basePath>/services/... >> This is a good question, I have not done it myself but I think it should JPU> work: >> the servlet dispatches according to registered services, in this regard JPU> JAX-RS and JAX-WS should not conflict. Does it work in your case? Thank you. >> Best Regards, >> Andriy Redko >>> Hi Andriy, >>> Using address="/" seems to work but still I don't understand how the >>> following work together: >>> - path specification in servlet mapping for the CXF servlet >>> (org.apache.cxf.transport.servlet.CXFServlet) >>> - the 'address' attribute on the jaxrs:server bean declaration >>> - the javax.ws.rs.Path or javax.jws.WebService annotation on the >>> service API description Say I've two services with (relateive to the >>> host) url's: >>> 1. a jaxrs server on url: '/<basePath>/services/service1' >>> 2. a jaxws service endpoint on '/<basePath>/services/service2' >>> How do I configure above 3 aspects? Currently I have (working): >>> 1.for the jaxrs:server endpoint: >>> - servlet path mapping: '/services/*' >>> - jaxrs-server address attribute: address="/" >>> - @Path annotation: @Path("service1") 2.For the jaxws >>> service endpoint: >>> - servlet path mapping: '/services/*' (JAXWS and JAXRS >>> requests are handleb by the same CXF servle) >>> - jaxws:endpoint server address attribute: >>> address="/service2" >>> - @WebService(name="service2") A correct request for >>> '1' would be '/basePath>/services/service1/<ID>'. >>> A correct request for '2' would be '/basePath>/services/service2'. >>> The jaxrs/jaxws configuration behavior seem to differ with respect to: >>> - the server address attribute >>> - The API annotation (@Path or @Webservice) The JAXWS server >>> address attribute doesn't seem to interfere with the @Webservice >>> annotation. While the jaxrs server address attribute does seem to >>> interfere with the @Path annotation. I would have expected the jaxrs >>> server aspects to be configured as: >>> - servlet path mapping: '/services/*' >>> - jaxrs-server address attribute: address="/service1" >>> - @Path annotation: @Path("service1") but then a valid >>> request would be >>>> /services/service1/service1/<ID>'. >>> For both the 'address' attribute is relative to the servlet path. >>> The @Path Javadoc mentions that this path is relative to the >>> ApplicationPath which thus seems to be relative to the jaxrs-server >>> address attribute. As for @Webservice it doesnn't seem to be url-path JPU> related. >>> Question: Because now address="/" is set for the jaxrs:server will it >>> also inspect requests targeted for the jaxws service as those >>> requests have start with the same path '/<basePath>/services/...'. >>> Albeit somewhat confusing. >>> J.P. >>> -----Original Message----- >>> From: Andriy Redko <drr...@gmail.com> >>> Sent: dinsdag 14 juni 2022 1:08 >>> To: Jean Pierre URKENS <jean-pierre.urk...@devoteam.com>; >>> iss...@cxf.apache.org; dev@cxf.apache.org >>> Subject: Re: JAXRS server endpoint not gracefully shutdown Hi Jean, >>> Indeed, the jaxrs:server does not expect address to be omitted, you >>> could use the "/" (and I believe an empty string would also make it): >>> <jaxrs:server id="restServer" basePackages="xxx" address="/"> ... >>> </jaxrs:server> >>> Thank you. >>> Hope it helps. >>> Best Regards, >>> Andriy Redko >>>> I create a JAXRS server endpoint (CXF 3.5.2) using spring bean >>>> declarations >>>> like: >>>> <jaxrs:server id="restServer" basePackages="xxx"> >>>> <jaxrs:serviceBeans> >>>> <ref bean="TestApi" /> >>>> </jaxrs:serviceBeans> >>>> <jaxrs:providers> >>>> <…/> >>>> </jaxrs:providers> >>>> <jaxrs:features> >>>> <… /> >>>> </jaxrs:features> >>>> <jaxrs:inInterceptors> >>>> <… /> >>>> </jaxrs:inInterceptors> >>>> <jaxrs:outInterceptors>* >>>> <**…**/>* >>>> </jaxrs:outInterceptors>* >>>> </jaxrs:server> >>>> Here my “TestApi” bean interface is declared like: >>>> @Path("accounts") >>>> @Consumes(MediaType.*APPLICATION_JSON*) >>>> @Produces(MediaType.*APPLICATION_JSON*) >>>> public interface TestApi { >>>> … >>>> } >>>> And CXF is triggered via a servlet configuration like: >>>> <servlet> >>>> <display-name>CXF Servlet</display-name> >>>> <servlet-name>CXFServlet</servlet-name> >>>> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servle >>>> t -class>>>>> >>>> </servlet> >>>> <servlet-mapping> >>>> <servlet-name>CXFServlet</servlet-name> >>>> <url-pattern>/services/*</url-pattern> >>>> </servlet-mapping> >>>> Because I’ve got the @Path declaration on the interface type I’ve >>>> omitted >>>> the address=”accounts” attribute on the jaxrs:server declaration >>>> since otherwise >>>> I noticed that the server would be listening to >>>> /basepath/services/ accounts/accounts/…). >>>> Now this configuration works perfectly, only when shutting down >>>> the application server cxf calls >>>> ServerImpl#destroy() >>>> which delegates (via Obeservable) to >>>> AbstractHTTPDestination#deactivate() >>>> which calls >>>> registry.removeDestination(path). >>>> This path is null (no ‘address’ specified on jaxrs:server >>>> declaration) and results in a NPE on the registry Map. >>>> This causes an unclean shutdown of my server. >>>> Is this an error in cxf or is my jaxrs:server configured incorrectly? >>>> How does the ‘address’ attribute on the jaxrs:server declaration >>>> correctly interact with the @Path parameter on the API interface? JPU> <<...>>