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-Contextanno >> 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="Au >> 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 <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}/cu >>>>> 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</servl >>>>>>> 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? >>>> <<...>>