Request mapping warnings

Still some minor issue related to request mapping.

I notice I am getting warnings like:

   *2023-07-19 13:08:23,022 [T8N1TP1-4] WARN
      (SID=8806F673DEC6B53D9248AF0DD81F6882)
      (org.apache.cxf.jaxrs.model.OperationResourceInfoComparatorBase:102)
- Both
      
be.dvtm.aeo.op.openapi.api.impl.KmopDienstverlenerApiServiceImpl#getDvlById
      and
      
be.dvtm.aeo.op.openapi.api.impl.KmopDienstverlenerApiServiceImpl#getDvlById
      are equal candidates for handling the current request which can lead to
      unpredictable results*

Obvious that they are equal candidates because they are the same class. But
what is the cause of this double detection?

Is it because when* JAXRSUtils.**getRootResources*(Message message)  gets
called, I see that it contains 4 entries:

·       (twice) KmopDienstverlenerApiServiceImpl -> my service endpoint

·       io.swagger.v3.jaxrs2.integration.resources.OpenApiResource

·       org.apache.cxf.jaxrs.swagger.ui.SwaggerUiService

So twice my service implementation, I wouldn’t know why this is the case?

On my classpath I have set:

·       cxf-rt-rs-service-description-3.5.6.jar                 -> this
handles request for ‘_wadl’

·       cxf-rt-rs-service-description-openapi-v3-3.5.6.jar      -> this
handles request for ‘openapi.[yaml|json]’

·       cxf-rt-rs-service-description-swagger-ui-3.5.6.jar      -> this
handles request for ‘Swagger documentation’

would this be a cause for my service endpoint to appear multiple times?
Aside from that I have no idea what could cause this.

J.P.

-----Original Message-----
From: Andriy Redko <[email protected]>
Sent: donderdag 13 juli 2023 18:24
To: Jean Pierre URKENS <[email protected]>; [email protected]
Subject: Re: How to setup multiple JAXRS server endpoints

Got it, thank you (the Swagger sometimes does surprising things).

Thursday, July 13, 2023, 1:33:07 AM, you wrote:

JPU> The @Parameter annotation seems to be ignored at this level.

JPU> -----Original Message-----

JPU> From: Jean Pierre URKENS <[email protected]>

JPU> Sent: donderdag 13 juli 2023 7:11

JPU> To: 'Andriy Redko' <[email protected]>; '[email protected]'

JPU> <[email protected]>

JPU> Subject: RE: How to setup multiple JAXRS server endpoints

JPU> Yes, SwaggerUI works too!

JPU> I noticed that v2.x of swagger-jaxrs relates to OpenApi v3.1.x

JPU> while my spec is compliant with OpenApi v3.0.x, so I am going to

JPU> stick with v2.1.13 which seems to be that last version for OpenApi
v3.0.x.

JPU> I thought the @Parameter only applied to input parameters ("query",

JPU> "header", "path" or "cookie" parameters), but I'll give it a try.

JPU> J.P.

JPU> -----Original Message-----

JPU> From: Andriy Redko <[email protected]>

JPU> Sent: woensdag 12 juli 2023 22:16

JPU> To: Jean Pierre URKENS <[email protected]>;

JPU> [email protected]

JPU> Subject: Re: How to setup multiple JAXRS server endpoints

JPU> Hi Jean,

JPU> That's awesome, have you got SwaggerUI working as well?

JPU> Yes, you could use 2.2.15 (we already updated to this version, no

JPU> regressions). It seems like the description applies to the whole

JPU> schema (which is the same for both properties), may be you could

JPU> use @Parameter

JPU> instead:

JPU> @Parameter(description="The description I want for prop1")

JPU> Thank you.

JPU> Best Regards,

JPU>     Andriy Redko

>> Hi Andriy,

>> After having migrated everything to "io.swagger.v3.oas.annotations.*"

>> the swagger endpoints for each of my services became active.

>> So far so good, but I do notice that there are discrepancies when

>> annotating models, e.g.:

>>  public class Model1 {

>>   @Schema(description="The description I want for prop1")

>>    private Model2 prop1;

>>   @Schema(description="The description I want for prop2")

>>    private Model2 prop2;

>>   ...

>> }

>> When I generate the openapi.[json|yaml] specification I see that both

>> prop1 and prop2 have a reference to the schema component "Model2"

>> with description ' The description I want for prop2' which is

>> inappropriate for 'prop1'.

>> It is not unlikely to have multiple properties within one Model that

>> are of the same class but are semantically used in a different context.
E.g.

>> something as simple as a ShipmentOrder having two 'Address'

>> properties 'from' and 'to' would result in wrong API documentation.

>> I am aware it has nothing to do with CXF but rather with

>> swagger-jaxrs2-vx.y.z.jar and depending libraries. CXF-3.5.6 has

>> dependency on swagger-jaxrs2-2.1.13.jar. Would it be an issue to

>> replace this dependency with e.g. swagger-jaxrs2-2.2.15.jar (latest

>> stable release according to maven central repo)?

>> J.P.

>> -----Original Message-----

>> From: Jean Pierre URKENS <[email protected]>

>> Sent: woensdag 12 juli 2023 8:25

>> To: 'Andriy Redko' <[email protected]>; '[email protected]'

>> <[email protected]>

>> Subject: RE: How to setup multiple JAXRS server endpoints I seem to

>> be mistaken here, the endpoint was loaded (I did a manual HTTP GET

>> test to the endpoint to verify this) although no breakpoints where

>> hit during startup.

>> I am first going to complete the migration to

>> "io.swagger.v3.oas.annotations.*" annotations for all endpoints and

>> then I am going to test again.

>> The application is composed of libraries, some of which use SLF4J but

>> most use LOG4J for logging.

>> J.P.

>> -----Original Message-----

>> From: Andriy Redko <[email protected]>

>> Sent: woensdag 12 juli 2023 1:13

>> To: Jean Pierre URKENS <[email protected]>;

>> [email protected]

>> Subject: Re: How to setup multiple JAXRS server endpoints Hi Jean,

>> The

>> OpenApiFeature$Portable#initiliaze(…) should definitely be called

>> (otherwise you shouldn't even see the openapi.json endpoint), so I am

>> not sure why these are not triggering for you.

>>

>> For logging, it seems like you are using SLF4J

>> (org.apache.cxf.common.logging.Slf4jLogger),

>> and also reload4j (aka log4j), why do you need both?

>> Thank you.

>> Best Regards,

>>     Andriy Redko

JPU>>> After some code investigation:

JPU>>> OpenApiFeature implements SwaggerUiSupport and in its

JPU>>> portable#registerSwaggerUiResources(…) method it will call

JPU>>> SwaggerUiSupport#getSwaggerUi(…) which will register the

JPU> SwaggerUiService.

JPU>>> I have put breakpoints on:

JPU>>>    - OpenApiFeature$Portable#initiliaze(…)

JPU>>>    - SwaggerUiService constructor

JPU>>>    - SwaggerUiSupport#getSwaggerUi(…)

JPU>>> but none of them are hit when starting my application?

JPU>>> Although the (spring) logging shows all beans in my

JPU>>> cxf-endpoints.xml have been created?

JPU>>> The *WADL* and *OpenAPI* endpoints to get the specification work.

JPU>>> Even the actual endpoint seems to work although I didn’t hit any

JPU>>> of the breakpoint?

JPU>>> CXF, also doesn’t seem to log a lot, I am hardly getting any log

JPU>>> entries although log level I set to DEBUG.

JPU>>> My logging (except wire message logging) for cxf is setup

JPU>>> correctly (I

JPU>>> think):

JPU>>>    - ../META-INF/cxf/org.apache.cxf.Logger contains the line

JPU>>>    ‘org.apache.cxf.common.logging.Slf4jLogger’

JPU>>>    - slf4j-api-1.7.36.jar, slf4j-reload4j-1.7.36.jar and

JPU>>>    reload4j-1.2.19.jar are on the classpath

JPU>>>    - the log4j.properties file contains the line:

JPU>>>    ‘log4j.logger.org.apache.cxf=DEBUG’

JPU>>> There are no special instructions mentioned on

JPU>>> https://cxf.apache.org/docs/general-cxf-logging.html so the above

JPU>>> should work (it works for all other packages I use in my
application).

JPU>>> J.P.

JPU>>> *From:* Jean Pierre URKENS <[email protected]>

JPU>>> *Sent:* dinsdag 11 juli 2023 9:58

JPU>>> *To:* 'Andriy Redko' <[email protected]>; '[email protected]' <

[email protected]>>>>

JPU>>> *Subject:* RE: How to setup multiple JAXRS server endpoints

JPU>>> Hi Andriy,

JPU>>> As a test I removed all JAX-RS endpoints that use Swagger v2

JPU>>> annotations from my configuration file (see attachment).

JPU>>> So I've now only 1 JAX-RS endpoint, fully annotated with Swagger

JPU>>> v3 annotations, using the OpenApiFeature i.o. Swagger2Feature.

JPU>>> If I run my server with this configuration I only get the

JPU>>> (working)

JPU>>> *WADL* and *OpenAPI* endpoints, no Swagger UI endpoint:



JPU>>> So there is some configuration missing to detect/activate the

JPU>>> Swagger endpoint. When I look at the samples that come with the

JPU>>> distribution of CXF (I am using v3.5.6) nothing special seems to

JPU>>> be

JPU> configured to activate this?

JPU>>> Do you have any idea how the SwaggerUiService is picked up when

JPU> loading?

JPU>>> J.P.

JPU>>> -----Original Message-----

JPU>>> From: Andriy Redko <[email protected]>

JPU>>> Sent: dinsdag 11 juli 2023 3:44

JPU>>> To: Jean Pierre URKENS <[email protected]>;

JPU>>> [email protected]

JPU>>> Subject: Re: How to setup multiple JAXRS server endpoints

JPU>>> Hi Jean,

JPU>>> I guess you figured one issue, swagger.json -> openapi.json, but

JPU>>> to be honest we have never tested or envisioned the application

JPU>>> that would use OpenAPI 2.0 (Swagger) and OpenAPI 3.0 at the same

JPU>>> time, I am afraid this is just not supported. You may get things

JPU>>> back on track when going with OpenAPI 3.0 for all services.

JPU>>> Thank you.

JPU>>> Best Regards,

JPU>>>     Andriy Redko



>>>> Hi Andriy,





>>>> I am trying to trace the difference in handling with another

>>>> application where I’ve got only one CXF service endpoint that uses

>>>> swagger v3 openapi annotations.

>>>> There I see that when handling the Swagger page request (

>>>> http://l-p53-008:8082/idb-fe/services/api-docs?url=openapi.json)

>>>> the JAXRSInInterceptor is calling:





>>>> *JAXRSUtils.**getRootResources*(Message message)





>>>> It contains 4 entries:

>>>>    - (twice) InkomOndernemingApiserviceImpl -> my service endpoint

>>>>    - io.swagger.v3.jaxrs2.integration.resources.OpenApiResource

>>>>    - org.apache.cxf.jaxrs.swagger.ui.SwaggerUiService













>>>> On the application described below with the service ‘oidcsim’ when

>>>> calling the swagger page request

>>>> (l-p53-008:8081/op/services/oidcsim/api-docs?url=openapi.json) the

>>>> result of the getRootResources doesn’t contain the

>>>> ClassResourceInfo ‘ SwaggerUiService’. It only contains 3 entries:

>>>>    - (twice) OidcProviderApiServiceImpl (my service endpoint)

>>>>    - io.swagger.v3.jaxrs2.integration.resources.OpenApiResource





>>>> The SwaggerUiService is the one that is configured to handle the

JPU>>> ‘api-docs’

>>>> path-request. Since it is missing the request is tried to match

>>>> with the other two resources but fails, hence ‘NOT FOUND’ exception.





>>>> I can’t trace back where these rootResources are set and why the

>>>> SwaggerUiService’ isn’t listed.





>>>> J.P.

>>>> *From:* Jean Pierre URKENS <[email protected]>

>>>> *Sent:* maandag 10 juli 2023 13:43

>>>> *To:* 'Andriy Redko' <[email protected]>

>>>> *Subject:* RE: How to setup multiple JAXRS server endpoints





>>>> Andriy,





>>>> I am trying to switch from Swagger v2 to OpenApi v3 annotations

>>>> basically because my starting point is an OpenApi v3.0.7 yaml file

>>>> description and OpenAPI seems to be the way forward.

>>>> For applications where I have only one CXF JAX-RS endpoint exposed

>>>> I had no problems converting. However as soon as there are multiple

>>>> endpoints I run into troubles.





>>>> So, to recall, I've an application exposing 3 JAX-RS endpoints that

>>>> where previously annotated with swagger v2 annotations (i.e.

>>>> package

>>>> io.swagger.annotations.*) which I migrated to

>>>> swagger v3 annotations (package io.swagger.v3.oas.annotations.*).

>>>> In accordance I altered my CXF JAX-RS endpoint configuration from

>>>> (only showing relevant parts, see attachment for full setup):





>>>>                <!-- CXF Swagger2Feature -->

>>>>                <bean id="SwaggerUiConfigOidcApi"

>>>> class="org.apache.cxf.jaxrs.swagger.ui.SwaggerUiConfig">

>>>>                               <property name="queryConfigEnabled"

>>>>                               <property name="url"

>>>> value="/op/services/oidcsim/swagger.yaml"/>

>>>>                </bean>

>>>>                <bean id="Swagger2FeatureOidcApi"

>>>> class="org.apache.cxf.jaxrs.swagger.Swagger2Feature">

>>>>                               <property name="basePath"

>>>> value="/op/services/oidcsim"/>

>>>>                               <property name="usePathBasedConfig"

>>>>                               <property name="resourcePackage"

>>>> value="be.dvtm.aeo.op.oidc"/>

>>>>                               <property name="supportSwaggerUi"

>>>>                               <property name="swaggerUiConfig"

>>>> ref="SwaggerUiConfigOidcApi"/>

>>>>                </bean>

>>>>                <jaxrs:server id="OidcProviderApiServer"

>>>> basePackages="be.dvtm.aeo.op.oidc" address="/oidcsim">

>>>>                               ....

>>>>                               <jaxrs:features>

>>>>                                              <ref

>>>> bean="Swagger2FeatureOidcApi" />

>>>>                               </jaxrs:features>

>>>>                               ...

>>>>                </jaxrs:server>





>>>> TO:

>>>>                <!-- CXF OpenAPIFeature -->

>>>>                <bean id="OidcSwaggerUiConfig"

>>>> class="org.apache.cxf.jaxrs.swagger.ui.SwaggerUiConfig">

>>>>                               <property name="queryConfigEnabled"

>>>>                               <property name="url"

>>>> value="openapi.json"/>

>>>>                </bean>

>>>>                <bean id="OidcOpenApiFeature"

>>>> class="org.apache.cxf.jaxrs.openapi.OpenApiFeature">

>>>>                               <property name="supportSwaggerUi"

>>>>                               <property name="swaggerUiConfig"

>>>> ref="OidcSwaggerUiConfig"/>

>>>>                               <property name="swaggerUiVersion"

>>>>                               <property name="scan" value="false"/>

>>>>                               <property name="useContextBasedConfig"

>>>>                               <property name="resourcePackages"

>>>> value="be.dvtm.aeo.op.oidc"/>

>>>>                </bean>

>>>>                <jaxrs:server id="OidcProviderApiServer"

>>>> basePackages="be.dvtm.aeo.op.oidc" address="/oidcsim">

>>>>                               ....

>>>>                               <jaxrs:features>

>>>>                                              <ref

JPU>>> bean="OidcOpenApiFeature"

>>>>                               </jaxrs:features>

>>>>                               ...

>>>>                </jaxrs:server>









>>>> Now when starting my application and navigating to the root part "

>>>> http://localhost:localPort/op/services"; I get an overview of all my

>>>> endpoints:





>>>> Now there are 3 RESTful service endpoints setup:

>>>>    1. ‘oidcsim’ which I switched to swagger v3 annotations

>>>>    2. ‘openapi’ currently still swagger v2 annotations

>>>>    3. ‘sdx’ currently still swagger v2 annotations





>>>> all endpoints work except for the ‘swagger endpoint address for the

>>>> oidcsim

>>>> endpoint:

>>>> http://l-p53-008:8081/op/services/oidcsim/api-docs?url=/op/services

>>>> /o

>>>> i

>>>> dcsim/swagger.json

>>>> So the *WADL* and *OpenAPI* endpoint work but not the *Swagger*

>>>> endpoint of the oidcsim resource. I am getting an error (the value

>>>> of the ‘url’ query parameter isn’t relevant):





>>>>         “WebApplicationException has been caught, status: 404,

>>>> message: HTTP 404 Not Found”





>>>> When I try (without the ‘/oidcsim’ context):

>>>> http://l-p53-008:8081/op/services/api-docs I get:

>>>>                “No service was found.”





>>>> So the endpoint http://l-p53-008:8081/op/services/oidcsim/api-docs

>>>> doesn’t exist, where as the endpoint

>>>> http://l-p53-008:8081/op/services/api-docs does exist but no

>>>> service

JPU>>> description is found?

>>>> Of course my intention is to get working, as previously with the

>>>> swagger v2 setup for which I then specifically added the

>>>> *Swagger2Feature* config

>>>> parameters:

>>>>                               <property name="basePath"

>>>> value="/op/services/oidcsim"/>

>>>>                               <property name="usePathBasedConfig"





>>>> But I don’t find the according configuration options for the

>>>> *OpenApiFeature* class or whether I should configure this in

>>>> another way.





>>>> Any suggestions on this?





>>>> Regards,





>>>> J.P.









>>>> -----Original Message-----

>>>> From: Andriy Redko <[email protected]>

>>>> Sent: donderdag 25 mei 2023 2:27

>>>> To: Jean Pierre URKENS <[email protected]>;

>>>> [email protected]

>>>> Subject: Re: How to setup multiple JAXRS server endpoints





>>>> Hi Jean,





>>>> You may run into Swagger JAX-RS scanner limitations, as far as I

>>>> can tell - it checks class annotations for SwaggerDefinition, does

>>>> not traverse the hierarchy [1].





>>>> [1]

>>>> https://github.com/swagger-api/swagger-core/blob/1.5/modules/swagge

>>>> r-

>>>> j

>>>> axrs/src/main/java/io/swagger/jaxrs/Reader.java#L194





>>>> Best Regards,

>>>>     Andriy Redko





>>>>>  RE: How to setup multiple JAXRS server endpoints





>>>>> Still one question );





>>>>> The generated swagger file doesn’t take into account the

>>>>> @SwaggerDefintion on my interface classes?





>>>>> As a test I looked at

>>>>> *https://github.com/apache/cxf/tree/3.6.x-fixes/distribution/src/m

>>>>> a

>>>>> in/release/samples/jax_rs/description_swagger2_web**

>>>>> and** modified** sample2*

>>>>> <https://github.com/apache/cxf/tree/3.6.x-fixes/distribution/src/m

>>>>> a

>>>>> in/release/samples/jax_rs/description_swagger2_web

>>>>> and modified sample2> as follows:





>>>>>    @Path("/sample2")





>>>>>       @Api(value = "/sample2",authorizations=

>>>>>       {@Authorization(value="bearer")},description = "Sample2

>>>> (modified) JAX-RS

>>>>>       service with Swagger documentation")





>>>>>       @SwaggerDefinition(





>>>>>               info = @Info(





>>>>>                       description = "Sample2 server",





>>>>>                       version="1.0",





>>>>>                       title = "Test2",





>>>>>                       contact = @Contact(name = "J.P. Urkens",email =
"

>>>>>       *[email protected]* <

>>>> [email protected]>

>>>>>       ")),





>>>>>               securityDefinition =

>>>>>       @SecurityDefinition(apiKeyAuthDefinitions=

>>>> *{@ApiKeyAuthDefinition(key="bearer",in=ApiKeyLocation.HEADER,name=
<*{@ApiKeyAuthDefinition(key=>

>>>> "A

>>>> u

>>>> thorization",description="Use*

>>>>>       <{@ApiKeyAuthDefinition(key=> the format 'Bearer

>>>>>       &lt;accessToken&gt;'")})





>>>>>       )





>>>>>       public class Sample2 {...}





>>>>> This correctly generates the ‘securityDefintions’ in the swagger file.





>>>>> If include the same @SwaggerDefinition and the authorizations on

>>>>> the @Api annotation as above in my interface classes then the

>>>>> generated swagger file doesn’t contain the ‘securityDefintions’ ?





>>>>> Any idea what I might be missing?





>>>>> Regards,





>>>>> J.P.





>>>>> -----Original Message-----

>>>>> From: Jean Pierre URKENS <[email protected]>

>>>>> Sent: dinsdag 23 mei 2023 12:52

>>>>> To: 'Andriy Redko' <[email protected]>; '[email protected]' <



>>>>> Subject: RE: How to setup multiple JAXRS server endpoints





>>>>> Hi Andriy,





>>>>> I added the parameter usePathBasedConfig=true to the

>>>>> Swagger2Feature bean declarations but still it does generate an

>>>>> empty swagger.yaml for interfaces KmopResources and

>>>>> KmopDienstverlener although I noticed that for these interfaces

>>>>> the

>>>>> @Path() annotation was commented out (as I included it in the

>>>>> server declaration). After providing an empty @Path("")

>>>>> declaration on

>>>> the API interface classes everything worked.





>>>>> Thanks for the support.





>>>>> -----Original Message-----





>>>>> From: Andriy Redko <[email protected]>





>>>>> Sent: dinsdag 23 mei 2023 3:42





>>>>> To: Jean Pierre URKENS <[email protected]>;

>>>>> [email protected]





>>>>> Subject: Re: How to setup multiple JAXRS server endpoints





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

>>>>> e

>>>>> gration-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/ma

>>>>> i

>>>>> n/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





>>>>>>  RE: How to setup multiple JAXRS server endpoints





>>>>>> Hi Andriy,





>>>>>> I am not quite understanding how to correctly configure the

>>>>> Swagger2Feature.





>>>>>> Referring to the attached cxf-endpoints configuration I (as a

>>>>>> test)





>>>>>> created





>>>>>> 3 JAXRS server instances:





>>>>>> 1.      A* KmopApiServer* server for the*





>>>>>> be.dvtm.aeo.op.sodexo.api.KmopApiService* interface, serving





>>>>>> requests for URI path:





>>>>>>        * <protocol>**//<host:<port>/op/services/accounts*





>>>>>>    ‘op’  = root path of the web application





>>>>>>             ‘services’ = servlet path of the CXF-servlet





>>>>>>       The address of the server is set to ‘/accounts’ and the

>>>>>> @Path(…)





>>>>>>       annotation on the interface class was cleared.





>>>>>> 2.      A* Kmop**Resources**ApiServer* server for the*

>>>> be.dvtm.aeo.op.*





>>>>>> *openapi.**api.Kmop**Recources**ApiService* interface, serving





>>>>>> requests for URI path:





>>>>>>        * <protocol>**//<host:<port>/op/services/**resources*





>>>>>> The address of the server is set to ‘/resources’ and the @Path(…)





>>>>>> annotation on the interface class was cleared.





>>>>>> 3.      A* Kmop**Dienstverlener**Server* server for the*

>>>>> be.dvtm.aeo.op.*





>>>>>> *openapi**.api.Kmop**Dienstverlener**Service* interface, serving





>>>>>> requests for URI path:





>>>>>>        * <protocol>**//<host:<port>/op/services/**dienstverlener*





>>>>>> The address of the server is set to ‘/dienstverlener’ and the





>>>>>> @Path(…) annotation on the interface class was cleared.





>>>>>> For each of these server instances I’ve set the Swagger2Feature





>>>>>> with configuration as indicated in the attached cxf-endpoints.xml.





>>>>>> With regard to the configurations for the Swagger2Feature I’ve

>>>>>> the





>>>>>> following questions:





>>>>>> a)      Referring to *

>>>> https://cxf.apache.org/docs/swagger2feature.html*





>>>>>> <https://cxf.apache.org/docs/swagger2feature.html>  could you





>>>>>> clarify on the following configuration parameters:





>>>>>> *i.     ** basePath* – Is this the path to the CXFServlet context (‘





>>>>>> /op/services’) or to the JAX-RS server instance (e.g.





>>>>>> ‘/op/services/accounts’) or still something else? Is it used to





>>>>>> resolve service classes or is it just for documentation in the

>>>>>> swagger

>>>>> file?





>>>>>> *ii.    ** resourcePackage* – the description mentions ‘package
names’





>>>>>> while the default mentions ‘service classes’? Service 2 and 3

>>>>>> above





>>>>>> are within the same package (generated from the same yaml





>>>>>> specification that included both interfaces).





>>>>>> *iii.   ** ig**noreRoutes* – is this taken into account when





>>>>>> scanAllResources=false?





>>>>>> *iv.    ** swaggerUiConfig* – What is the correct ‘url’ parameter

>>>> value





>>>>>> (cf. question ‘a’)?





>>>>>> b)      What would be the correct URL to generate a swagger.yaml

>>>>>> file

>>>>> for





>>>>>> each of the above interfaces? Initially I called:





>>>>>> *i.     **

>>>>> <protocol>**//<host:<port>/op/services/accounts**/swagger.yaml*





>>>>>> *ii.    **

>>>>> <protocol>**//<host:<port>/op/services/**resources/swagger.yaml*





>>>>>> *iii.   ** <protocol>**//<host:<port>/op/services/**dienstver*





>>>>>> *lener/swagger.yaml*





>>>>>>    All three requests delivered the same yaml specification,

>>>>>> namely

>>>>> the one





>>>>>>       for interface* KmopApiServer*?





>>>>>> c)      I tried to debug the processing of the requests under ‘b)’

>>>>>> and

>>>>> this





>>>>>> is done by the class JAXRSInterceptor#processRequest where the





>>>>>> MessageImpl object for request “ii.” looks like the one attached.





>>>>>> It finds 3 resource





>>>>>> classes:





>>>>>>    be.dvtm.aeo.op.openapi.api.impl.KmopResourcesApiServiceImpl





>>>>>>       org.apache.cxf.jaxrs.swagger.Swagger2ApiListingResource





>>>>>>       org.apache.cxf.jaxrs.swagger.ui.SwaggerUiService





>>>>>> è       It matches the request to resource*

>>>>> Swagger2ApiListingResource* with





>>>>>> UriInfo={type=[yaml], FINAL_MATCH_GROUP=[/]}} and calling its*





>>>>>> process(…)* method.





>>>>>> è       Here it seems to go wrong. It generates a

>>>> SwaggerContextService





>>>>>> having basePath=/op/services/resources/,swaggerConfig=null,





>>>>>> usePathBasedConfig=null and then calls





>>>>>> SwaggerContextService.getSwagger()





>>>>>> which returns the Swagger definition for interface KmopApiServer?





>>>>>> It looks like it caches generated swagger definitions based on a





>>>>>> configIdKey with prefix ’swagger.config.id.xxx’. This key is the





>>>>>> same for all 3 interfaces as usePathBasedConfig=null





>>>>>> and maps to ‘swagger.config.id.default’. The usePathBasedConfig

>>>>>> is





>>>>>> derived from the ServletConfig parameter





>>>>>> ‘swagger.use.path.based.config’.* So should this be set on the





>>>>>> declaration of the CXFServlet** in web.xml?*





>>>>>> è       Actually the SwaggerConfig, the JaxrsScanner and the

>>>>>> generated

>>>>> Swagger





>>>>>> are cached using keys like





>>>>>> ‘swagger.config.id.[default|baseUriPath]’, ‘





>>>>>> scanner.config.id.[default|baseUriPath]’. Caching with ‘baseUriPath’

>>>>> is only done when usePathBasedconfig=true.





>>>>>> è       If I patch this to true then configIdKey=’





>>>>>> swagger.config.id./op/services/resources/’ and no swagger entry

>>>>>> is





>>>>>> cached for this key so it will generate a new one. Again by





>>>>>> patching





>>>>>> SwaggerContextService.isUsePathBasedConfigInitParamDefined(sc)=tr

>>>>>> u

>>>>>> e





>>>>>> it will call: “swagger = scan(app, servletContext, sc, uriInfo);”





>>>>>> è       Again Scanners are cached and if usePathBasedConfig=null it

>>>>> will use





>>>>>> the one cached under  ‘swagger.scanner.id.default’ and this again





>>>>>> returns the swagger definition for the KmopApiService interface.





>>>>>> è       So patching usePathBasedConfig=true will return a new one





>>>>>> (DefaultJaxrsScanner). The classes to scan for in this new

>>>>>> scanner





>>>>>> are ‘

>>>>>> be.dvtm.aeo.op.openapi.api.impl.KmopResourcesApiServiceImpl‘





>>>>>> which is correct. It will generate a new (but empty) Swagger object.





>>>>>> è       Next Swagger2ApiListingResource will call the





>>>>>> customizer.customize(s), which still isn’t putting anything new

>>>>>> in





>>>>>> the Swagger object. Should it or should the next step do this?





>>>>>> è       Next BaseApiListingResource#getListing(…) is called which on

>>>>> its





>>>>>> turn calls getListingYamlResponse(..)





>>>>>> è       The final result is a swagger.yaml document with following

>>>>> content:





>>>>>>    swagger: "2.0"





>>>>>>       info:





>>>>>>         license:





>>>>>>           name: "Apache 2.0 License"





>>>>>>           url: http://www.apache.org/licenses/LICENSE-2.0.html





>>>>>>       basePath: "/op/services/resources"





>>>>>>        So basically an empty swagger file.





>>>>>> d)      The usePathBasedConfig is derived from the ServletConfig

>>>>> parameter ‘





>>>>>> swagger.use.path.based.config’. Without this parameter set to

>>>>>> true





>>>>>> there will be only one Swaggerconfig, JaxrsScanner and Swagger





>>>>>> object.* So should this be set on the declaration of the





>>>>>> CXFServlet** in web.xml?*





>>>>>> The majority in this processing happens in the library





>>>>>> swagger-jaxrs-v1.6.10 which is included as a dependency on

>>>>> cxf-rt-rs-service-description-swagger.





>>>>>> Even if I patch usePathBasedConfig=true about everywhere where I





>>>>>> met this it still doesn’t generate a correct swagger.yaml. Am I





>>>>>> still missing some configuration parameter?





>>>>>> Any suggestions on how to resolve this would be welcome.





>>>>>> Regards,





>>>>>> J.P. Urkens









































>>>>>> <<...>> <<...>>





>>>>>> -----Original Message-----





>>>>>> From: Andriy Redko <[email protected]>





>>>>>> Sent: maandag 8 mei 2023 23:15





>>>>>> To: Jean Pierre URKENS <[email protected]>; CXF Dev





>>>>>> List <











>>>>>> Subject: Re: How to setup multiple JAXRS server endpoints





>>>>>> Hi Jean,





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





>>>>>> changed them to @Path(“”). That does seems to work except the





>>>>>> swagger stuff no longer correctly works.





>>>>>> This is one of the possible options but OpenAPI/Swagger gets





>>>>>> confused for a





>>>>>> reason: the path is now implicit (not in the spec).





>>>>>> So how about this option:





>>>>>>  - use only one JAX-RS server (address "/")





>>>>>>  - host both resources but use @Path("accounts") and





>>>>>> @Path("resources") on them respectively









>>>>>> I see that for @Path("accounts") you need to apply the





>>>>>> "kmopApiAuthorizationFilter", that could be done using





>>>>>> DynamicFeature [1], [2]. If this is not the option and you would





>>>>>> prefer to use 2 separate JAX-RS servers, you may need to provide





>>>>>> your own instance of Swagger2Customizer [3], [4] which allows to





>>>>>> transform the OpenAPI/Swagger on the fly. Please let me know if

>>>>>> that

>>>>> would it work for you, thank you.





>>>>>> [1]





>>>>>> https://docs.oracle.com/javaee/7/api/javax/ws/rs/container/Dynami

>>>>>> c

>>>>>> F





>>>>>> eature.html





>>>>>> [2]





>>>>>> https://aredko.blogspot.com/2016/02/your-jax-rs-apis-were-not-bor

>>>>>> n

>>>>>> -





>>>>>> equal.html





>>>>>> [3]





>>>>>> https://cxf.apache.org/javadoc/latest/org/apache/cxf/jaxrs/swagge

>>>>>> r

>>>>>> /





>>>>>> Swagger2Customizer.html





>>>>>> [4] https://cxf.apache.org/docs/swagger2feature.html (has





>>>>>> customizer





>>>>>> property)









>>>>>> Best Regards,





>>>>>>     Andriy Redko





>>>>>>> Hi Andriy,





>>>>>>> I am again getting into trouble with server endpoint declarations.





>>>>>>> Now





>>>>>> because I am adding additional JAX-RS endpoints.





>>>>>>> The issue is with:





>>>>>>> 1.      The 'address' attribute on the <jaxrs:server> declaration

>>>>>>> in





>>>>>> combination with





>>>>>>> 2.      The 'url-pattern' for the CXFServlet declaration in the

>>>>>>> web.xml





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





>>>>>> one JAXRS server endpoint with declarations like:





>>>>>>> 1.      <jaxrs:server id="restServer"





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





>>>>>> interface method





>>>>>>> A valid API call would thus be e.g.:





>>>>>>> https://<hostname>:<port>/op/services/accounts/{authorizationId}

>>>>>>> /c

>>>>>>> u

>>>>>>> s

>>>>>>> t





>>>>>>> o





>>>>>>> merFund





>>>>>>> And this works correctly.





>>>>>>> We're now introducing additional JAX-RS service endpoints and

>>>>>>> now I





>>>>>>> am





>>>>>> running into problems. This second endpoint was declared with:





>>>>>>> 1.      <jaxrs:server id="resourceServer"





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





>>>>>> https://<hostname>:<port>/op/services/resources/NACE.





>>>>>>> The problem is that I can not declare two <jaxrs:server> entries

>>>>>>> with





>>>>>>> the





>>>>>> same ‘address’ as it throws the exception:





>>>>>>> Caused by:

>>>>>>> org.apache.cxf.service.factory.ServiceConstructionException:





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





>>>>>> the interface classes. By doing so the <jaxrs:server> bean





>>>>>> declarations no longer loads successfully.





>>>>>>> So I tried to keep the @Path declaration on the interface

>>>>>>> classes

>>>>>>> but





>>>>>> changed them to @Path(“”). That does seems to work except the





>>>>>> swagger stuff no longer correctly works.





>>>>>>> So what is the decent way to setup multiple JAX-RS server

>>>>>>> endpoints





>>>>>>> where





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





>>>>>> 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 <[email protected]>





>>>>>>> Sent: zaterdag 18 juni 2022 1:12





>>>>>>> To: Jean Pierre URKENS <[email protected]>;





>>>>>>> [email protected]; [email protected]





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





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





>>>>>> inside the SOAP message behind <baseUrl>/<servlet path mapping>/





>>>>>> (@Path / @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





>>>>>> work:





>>>>>>> the servlet dispatches according to registered services, in this





>>>>>>> regard





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





>>>>>> 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 <[email protected]>





>>>>>>>> Sent: dinsdag 14 juni 2022 1:08





>>>>>>>> To: Jean Pierre URKENS <[email protected]>;





>>>>>>>> [email protected]; [email protected]





>>>>>>>> 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</se

>>>>>>>>> rv

>>>>>>>>> l

>>>>>>>>> e





>>>>>>>>> t











>>>>>>>>>        </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?





>>>>>> <<...>>

Reply via email to