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
>>>>> <accessToken>'")})
>>>>> )
>>>>> 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?
>>>>>> <<...>>