Using javax.ws.rs.core.SecurityContext works.

Best Regards,

J.P.

-----Original Message-----
From: Andriy Redko <drr...@gmail.com>
Sent: vrijdag 2 juni 2023 23:11
To: Jean Pierre URKENS <jean-pierre.urk...@devoteam.com>; CXF Dev List
<dev@cxf.apache.org>
Subject: Re: Handle Bearer authorization

Hi Jean,

Apologies since I am rarely touching this part of the project, and do have
some knowledge gaps there. Anyway, the flow I was sure should work actually
does not [1] apparently. There are 2 security contexts actually:

 - javax.ws.rs.core.SecurityContext (or jakarta.ws.rs.core.SecurityContext)
 - org.apache.cxf.security.SecurityContext

I was thinking about the latter but due to [1], the injection does not work.
Could you try to use javax.ws.rs.core.SecurityContext instead please to see
what is being injected to you?

Thank you.

[1] https://issues.apache.org/jira/browse/CXF-5803

Best Regards,
    Andriy Redko

> I did a test where I:
> - created my own SecurityContext implementation
> - in my authentication filter I construct an instance 'sc' of this
> SecurityContext and put in the message using:
> JAXRSUtils.getCurrentMessage().put(SecurityContext.class, sc);

> I tried two ways to obtain this SecurityContext my service methods:
>  1. using annotations:
>         Interface:                 Response
> getOnderneming(@HeaderParam("X-KMO-OPERATION-ID") UUID
> operationId,@PathParam("kboNr")  String kboNr,@Context SecurityContext
> sc);
>         Implementation:    Response getOnderneming(UUID operationId,
> String kboNr,
> SecurityContext sc){...}  2.without annotations:
>         Interface:                 Response
> getOnderneming(@HeaderParam("X-KMO-OPERATION-ID") UUID
> operationId,@PathParam("kboNr")  String kboNr);
>         Implementation:    Response getOnderneming(UUID operationId,
> String kboNr,
> SecurityContext sc){
>                                 SecurityContext sc =
> JAXRSUtils.getCurrentMessage().get(SecurityContext.class);
>                                 ...
>                              }Using the annotations (1. above) way
> doesn't work the SecurityContext object 'sc' is null on entering the
> getOnderneming() method.
> Without annotations  (2. Above) I do get a valid SecurityContext
> object 'sc'.

> Isn't the 'annotations'-way supposed to work this way?

> Regards,

> J.P. Urkens

> -----Original Message-----
> From: Jean Pierre URKENS <jean-pierre.urk...@devoteam.com>
> Sent: vrijdag 2 juni 2023 10:18
> To: 'Andriy Redko' <drr...@gmail.com>
> Subject: RE: Handle Bearer authorization

> Hi Andriy,

> As far as I understand the filters JwtAuthenticationFilter and
> AbstractJwtAuthenticationFilter the assumption is that a request is
> received with an 'Authentication' header that contains a signed JWT
> token. The filter provides in methods to:
> -  validate the signed JWT token
> - to create a SecurityContext (JwtTokenSecurityContext) from it.

> This isn't the situation I am dealing with. I am receiving a request
> with an 'Authorization' header containing 'Bearer <access_token>'.
> I've no knowledge about the nature of this access_token, nor do I need
> to since validating this access token is done by sending a request to
> an 'OAuth/OIDC introspection endpoint' passing on this access_token.
> The introspection endpoint replies with a scope object (JWT claims
> object) if the token is valid.

> Now I can deal with this situation and create my own SecurityContext
> (extended from ClaimsSecurityContext). What I don't understand is how
> I get this SecurityContext available in my service method.

> I see that the AbstractJwtAuthenticationFilter (line 56) puts the
> constructed SecurityContext in the Message:
>         if (securityContext != null) {
>
> JAXRSUtils.getCurrentMessage().put(SecurityContext.class,
> securityContext);
>         }

> Can I simply retrieve this in my service method by calling:
>         SecurityContext sc =
> JAXRSUtils.getCurrentMessage().get(SecurityContext.class);

> So no need to add  @Context annotations to service methods like e.g.:

> Interface:                 Response
> getOnderneming(@HeaderParam("X-KMO-OPERATION-ID") UUID
> operationId,@PathParam("kboNr")  String kboNr,@Context SecurityContext
> ctx);
> Implementation:    Response getOnderneming(UUID operationId, String kboNr,
> SecurityContext sc){...}

> Regards,

> J.P.
> -----Original Message-----
> From: Andriy Redko <drr...@gmail.com>
> Sent: vrijdag 2 juni 2023 0:29
> To: Jean Pierre URKENS <jean-pierre.urk...@devoteam.com>; CXF Dev List
> <dev@cxf.apache.org>
> Subject: Re: Handle Bearer authorization

> Hi Jean,

> You should be able to get access to the Bearer and claims using
> JwtAuthenticationFilter + @Context SecurityContext The expected type
> of the security context should be ClaimsSecurityContext, with
> collection of claims being available.
> If the JwtAuthenticationFilter does not work for you (for some
> reasons), you could subclass AbstractJwtAuthenticationFilter.
> Hope it helps, thank you.

> Best Regards,
>     Andriy Redko

>> Hi Andriy,

>> I am lost in JAXRS JOSE security to figure out how to handle bearer
>> authorization. So what I currently did is:
>>   1. I created an ContainerRequestFilter to retrieve the Bearer
>> access token from the request and query the introspection endpoint
>> which returns the JWTClaims
>>   2.I added this filter in the Ininterceptor chain

>> This works, i.e. the filter is hit and it queries the introspection
>> endpoint which returns JWTClaims. The problem is that I need these
>> claims available in my service methods and I don't know how to pass
>> them from the ContainerRequestFilter to my service method. Thus far I
>> have been looking to save the JWTClaims as a property in the
>> ContainerRequestContext  which is available in my filter and inject
>> this context in my service methods with the @Context annotation. As
>> documented in
>> https://cxf.apache.org/docs/jax-rs-basics.html#JAXRSBasics-Contextann
>> o tations a number of context types can be injected with the @Context
>> annotation but I am not sure I can inject a ContainerRequestContext.

>> So I annotated my interface method as:
>>                 Response getOnderneming(
>>                         @HeaderParam("X-KMO-OPERATION-ID")
>> @NotNull(message="ERROR_2121") UUID operationId,
>>                         @PathParam("kboNr")
>> @NotNull(message="ERROR_2119") @Pattern(regexp =
>> "^\\d{10}$",message="ERROR_2216") String kboNr,
>>                         @Context ContainerRequestContext ctx);  And
>> my implementation method as:
>>                 Response getOnderneming(UUID operationId, String
>> kboNr, ContainerRequestContext ctx)

>> Unfortunately the ctx=null when the implementation method is called.

>> So my questions are:
>>  1.Is there a way to get the ContainerRequestContext available in my
>> service methods?
>>  2.If the answer to '1.' Is no how do I pass information constructed
>> in request filters to my service methods?
>>  3.Generally, is this the correct way to handle bearer authorization?
>> There is a lot of stuff in cxf-rt-rs-security-jose-(jaxrs) but I
>> can't really figure out how to use it. Anyway it is not sufficient
>> for me to have a filter that validates the bearer token. I need the
>> associated 'scope'
>> information in my service method as it contains information I'll need
>> in my business methods.

>> Regards,

>> J.P. Urkens

>> -----Original Message-----
>> From: Jean Pierre URKENS <jean-pierre.urk...@devoteam.com>
>> Sent: donderdag 25 mei 2023 9:48
>> To: 'Andriy Redko' <drr...@gmail.com>; 'dev@cxf.apache.org'
>> <dev@cxf.apache.org>
>> Subject: RE: How to setup multiple JAXRS server endpoints

>> Hi Andriy,

>> The issue seems to be that the Reader is scanning the implementation
>> classes while the @SwaggerDefinition (and all other swagger
>> annotations) were on the interface class.

>> So
>> https://github.com/swagger-api/swagger-core/blob/1.5/modules/swagger-
>> j axrs/src/main/java/io/swagger/jaxrs/Reader.java#L171,
>> scanning for @SwaggerDefinition, doesn't get triggered.
>> However via
>> https://github.com/swagger-api/swagger-core/blob/1.5/modules/swagger-
>> j axrs/src/main/java/io/swagger/jaxrs/Reader.java#L176,
>> through reflection, the remaining swagger annotation information is
>> retrieved, just not the @SwaggerDefinition.

>> So, I moved the @SwaggerDefintion to the implementation class and now
>> it is ok.

>> Thanks for the advice,

>> J.P.

>> -----Original Message-----
>> From: Andriy Redko <drr...@gmail.com>
>> Sent: donderdag 25 mei 2023 2:27
>> To: Jean Pierre URKENS <jean-pierre.urk...@devoteam.com>;
>> dev@cxf.apache.org
>> 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/swagger-
>> 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/ma
>>> in/release/samples/jax_rs/description_swagger2_web**
>>> and** modified** sample2*
>>> <https://github.com/apache/cxf/tree/3.6.x-fixes/distribution/src/ma
>>> 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 = "
>>>       *jean-pierre.urk...@devoteam.com*

>> <jean-pierre.urk...@devoteam.com>
>>>       ")),

>>>               securityDefinition =
>>>       @SecurityDefinition(apiKeyAuthDefinitions=

>> *{@ApiKeyAuthDefinition(key="bearer",in=ApiKeyLocation.HEADER,name="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 <jean-pierre.urk...@devoteam.com>
>>> Sent: dinsdag 23 mei 2023 12:52
>>> To: 'Andriy Redko' <drr...@gmail.com>; 'dev@cxf.apache.org' <

>>> 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 <drr...@gmail.com>

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

>>> To: Jean Pierre URKENS <jean-pierre.urk...@devoteam.com>;
>>> dev@cxf.apache.org

>>> 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---Inte
>>> 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/mai
>>> 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)=tru
>>>> 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 <drr...@gmail.com>

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

>>>> To: Jean Pierre URKENS <jean-pierre.urk...@devoteam.com>; 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/Dynamic
>>>> F

>>>> eature.html

>>>> [2]

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

>>>> equal.html

>>>> [3]

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

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

>>>> endpoint path would be:

>>>>>     <baseUrl>/<servlet path

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