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> <<...>>

Reply via email to