Hi Jean, My apologies for late response but it seems like you have found the issue :-). However am a bit surprised by the way you are using Content-Encoding [1]. I would expect the charset to be passed along with content type:
Response .status(Status.OK) .entity(dvlInfo) .type(MediaType.APPLICATION_JSON_TYPE.withCharset("UTF-8")) .build(); But not as Content-Encoding header which seems to be not strictly correct usage [2]. Hope it makes sense, thank you. [1] https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Encoding [2] https://stackoverflow.com/questions/17154967/is-content-encoding-being-set-to-utf-8-invalid Best Regards, Andriy Redko JPU> Hi andriy, JPU> As far as I could trace this the problem seems to be with the logging of the JPU> incoming response message only. JPU> In the method HttpConduit#handleResponseInternal the inMessage has: JPU> org.apache.cxf.message.Message.PROTOCOL_HEADERS={content-encoding=[UTF-8], JPU> Content-Length=[841], content-type=[application/json], Date=[Tue, 16 May JPU> 2023 10:23:41 GMT], Server=[Jetty(9.4.46.v20220331)]} JPU> But the call to "updateResponseHeaders(inMessage)" only examines the JPU> 'content-type' protocol header not the 'content-encoding' header. So the JPU> inMessage will not have set the 'Message.CONTENT_TYPE' as a result the JPU> subsequent line of code (line 1682): JPU> String charset = JPU> HttpHeaderHelper.findCharset((String)inMessage.get(Message.CONTENT_TYPE)); JPU> returns 'null' resulting in normalizedEncoding=ISO-8859-1. JPU> Is this a bug? JPU> J.P. JPU> -----Original Message----- JPU> From: Jean Pierre URKENS <jean-pierre.urk...@devoteam.com> JPU> Sent: maandag 15 mei 2023 16:46 JPU> To: 'Andriy Redko' <drr...@gmail.com> JPU> Subject: Mismatch in content encoding between client and server JPU> Hi Andriy, JPU> I got my services installed but when performing some local (JUnit) tests I JPU> notice that I am losing the content-encoding. JPU> E.g. in below message logging from CXF the country 'België' is passed in the JPU> response which has the header content-encoding=UTF-8 set. JPU> When reading/parsing the response it results in ' België' ? JPU> What does the server/client need to do to make sure the content is correctly JPU> encoded/decoded when: JPU> - the server writes the result entity in the reponse (I used JPU> "Response.status(Status.OK).entity(dvlInfo).type(MediaType.APPLICATION_JSON).encoding("UTF-8").build()") JPU> - the client reads the result entity from the response (I didn't directly JPU> see anything to inform the reader that the content is UTF-8 encoded so it is JPU> currently read by the client as "resp.readEntity(Dienstverlener.class)") JPU> Below the CXF message logging: JPU> KMOP] 2023-05-15 16:29:38,503 [main] INFO $--$ JPU> (org.slf4j.helpers.MarkerIgnoringBase:95) - REQ_OUT JPU> Address: JPU> http://localhost:8185/op/services/dienstverlener/dienstverlener/findErkendByErkNr?erkNr=DV.O235055 JPU> HttpMethod: GET JPU> Content-Type: application/json JPU> ExchangeId: 569ef415-99f7-41c2-956e-38e47ea8e4e5 JPU> Headers: {Accept=application/json, JPU> X-KMO-OPERATION-ID=ceaa4c95-0677-4510-b574-d99d82a45545, JPU> Content-Type=application/json} JPU> [KMOP] 2023-05-15 16:29:38,745 [qtp1348937989-29] INFO $--$ JPU> (org.slf4j.helpers.MarkerIgnoringBase:95) - REQ_IN JPU> Address: JPU> http://localhost:8185/op/services/dienstverlener/dienstverlener/findErkendByErkNr?erkNr=DV.O235055 JPU> HttpMethod: GET JPU> Content-Type: application/json JPU> ExchangeId: 0c78ff64-8016-4809-adf8-691d786d0dfd JPU> Headers: {Accept=application/json, Cache-Control=no-cache, JPU> User-Agent=Apache-CXF/3.5.2, JPU> X-KMO-OPERATION-ID=ceaa4c95-0677-4510-b574-d99d82a45545, JPU> connection=keep-alive, content-type=application/json, Host=localhost:8185, JPU> Pragma=no-cache} JPU> [KMOP] 2023-05-15 16:29:38,751 [qtp1348937989-29] DEBUG $--$ JPU> (be.xm.base.database.DBPoolManager:192) - Getting DBase connection from JPU> DBPoolManager for DataSource name=DEFAULT_DS [KMOP] 2023-05-15 16:29:38,752 JPU> [qtp1348937989-29] DEBUG $--$ (be.xm.base.database.DBPoolManager:195) - JPU> Found DataSource=oracle.jdbc.pool.OracleDataSource@77be656f for DataSource JPU> name=DEFAULT_DS [KMOP] 2023-05-15 16:29:39,091 [qtp1348937989-29] DEBUG $--$ JPU> (be.xm.base.database.DBPoolManager:202) - Obtained DBase JPU> connection(1995619431,autoCommit=true) from datasource DEFAULT_DS in JPU> 338.9987 milliseconds. JPU> [KMOP] 2023-05-15 16:29:39,346 [qtp1348937989-29] DEBUG $--$ JPU> (be.xm.base.database.DBHelper:386) - executed SQL-query JPU> 'selDvlInfoForMMByErkNrAsJson' : obtained DBase resultset in 190.5721 JPU> milliseconds. JPU> [KMOP] 2023-05-15 16:29:39,352 [qtp1348937989-29] DEBUG $--$ JPU> (be.xm.base.database.DBHelper:395) - executed SQL-query JPU> 'selDvlInfoForMMByErkNrAsJson' : processed DBase resultset (1st record) in JPU> 5.4814 milliseconds. JPU> [KMOP] 2023-05-15 16:29:39,352 [qtp1348937989-29] DEBUG $--$ JPU> (be.xm.base.database.DBHelper:433) - Closing DBase JPU> connection(1995619431,autoCommit=true) JPU> [KMOP] 2023-05-15 16:29:39,391 [qtp1348937989-29] INFO $--$ JPU> (org.slf4j.helpers.MarkerIgnoringBase:95) - RESP_OUT JPU> Address: JPU> http://localhost:8185/op/services/dienstverlener/dienstverlener/findErkendByErkNr?erkNr=DV.O235055 JPU> Content-Type: application/json JPU> ResponseCode: 200 JPU> ExchangeId: 0c78ff64-8016-4809-adf8-691d786d0dfd JPU> Headers: {Content-Encoding=UTF-8, Date=Mon, 15 May 2023 14:29:39 GMT, JPU> Content-Type=application/json} JPU> Payload: {"id":325943,"naam":"Qrios campus Aarschot","MZnaam":"QRIOS vzw JPU> ","kboNr":"0422695514","erkenningen":[{"dienst":"opleiding","nummer":"DV.O235055","erkendTot":"9999-01-01"}],"themas":[100000,100002,100010,100011,102290,102291,102292],"beoordelingen":[{"dienst":"opleiding","aantalBeoordelingen":10,"score":4.5}],"adres":{"land":"België","postcode":"3200","gemeente":"Aarschot","straat":"Bekaflaan","huisNummer":"62","busNummer":null},"contact":{"contactPersoon":"Peter JPU> Holsters","telNr":"003216551115","faxNr":null,"email":"aarsc...@qrios.be","website":"http://www.qrios.be"},"beschrijving":"Opleidingsverstrekker JPU> opleidingen voor JPU> volwassenen","banner":"http://AEODEV.BE.DEVOTEAM.COM:8081/images/op/dvl/banner_325943.png","logo":"http://AEODEV.BE.DEVOTEAM.COM:8081/images/op/dvl/logo_325943.png","latitude":50.98734451,"longitude":4.8472477} JPU> [KMOP] 2023-05-15 16:29:39,399 [main] INFO $--$ JPU> (org.slf4j.helpers.MarkerIgnoringBase:95) - RESP_IN JPU> Address: JPU> http://localhost:8185/op/services/dienstverlener/dienstverlener/findErkendByErkNr?erkNr=DV.O235055 JPU> Content-Type: application/json JPU> ResponseCode: 200 JPU> ExchangeId: 569ef415-99f7-41c2-956e-38e47ea8e4e5 JPU> Headers: {Server=Jetty(9.4.46.v20220331), content-encoding=UTF-8, JPU> content-type=application/json, Content-Length=841, Date=Mon, 15 May 2023 JPU> 14:29:39 GMT} JPU> Payload: {"id":325943,"naam":"Qrios campus Aarschot","MZnaam":"QRIOS vzw JPU> ","kboNr":"0422695514","erkenningen":[{"dienst":"opleiding","nummer":"DV.O235055","erkendTot":"9999-01-01"}],"themas":[100000,100002,100010,100011,102290,102291,102292],"beoordelingen":[{"dienst":"opleiding","aantalBeoordelingen":10,"score":4.5}],"adres":{"land":"België","postcode":"3200","gemeente":"Aarschot","straat":"Bekaflaan","huisNummer":"62","busNummer":null},"contact":{"contactPersoon":"Peter JPU> Holsters","telNr":"003216551115","faxNr":null,"email":"aarsc...@qrios.be","website":"http://www.qrios.be"},"beschrijving":"Opleidingsverstrekker JPU> opleidingen voor JPU> volwassenen","banner":"http://AEODEV.BE.DEVOTEAM.COM:8081/images/op/dvl/banner_325943.png","logo":"http://AEODEV.BE.DEVOTEAM.COM:8081/images/op/dvl/logo_325943.png","latitude":50.98734451,"longitude":4.8472477} JPU> -----Original Message----- JPU> From: Jean Pierre URKENS <jean-pierre.urk...@devoteam.com> JPU> Sent: dinsdag 9 mei 2023 9:25 JPU> To: 'Andriy Redko' <drr...@gmail.com> JPU> Subject: RE: How to setup multiple JAXRS server endpoints JPU> Hi Andriy, JPU> Both servers have not only differences in 'authorization' but also in JPU> exception handling regarding mapping and validation errors that's why I JPU> can't use the same JAX-RS server bean for them. I'll have a look at JPU> customizing the swagger feature and will come back on it but for now getting JPU> the server up-and-running is more important. JPU> Regards, JPU> J.P. Urkens JPU> -----Original Message----- JPU> From: Andriy Redko <drr...@gmail.com> JPU> Sent: maandag 8 mei 2023 23:15 JPU> To: Jean Pierre URKENS <jean-pierre.urk...@devoteam.com>; CXF Dev List JPU> <dev@cxf.apache.org> JPU> Subject: Re: How to setup multiple JAXRS server endpoints JPU> Hi Jean, JPU> Indeed the way you would like to do that is somewhat tricky. >> So I tried to keep the @Path declaration on the interface classes but >> changed them to @Path(“”). That does seems to work except the swagger >> stuff no longer correctly works. JPU> This is one of the possible options but OpenAPI/Swagger gets confused for a JPU> reason: the path is now implicit (not in the spec). JPU> So how about this option: JPU> - use only one JAX-RS server (address "/") JPU> - host both resources but use @Path("accounts") and @Path("resources") on JPU> them respectively JPU> I see that for @Path("accounts") you need to apply the JPU> "kmopApiAuthorizationFilter", that could be done using DynamicFeature [1], JPU> [2]. If this is not the option and you would prefer to use 2 separate JAX-RS JPU> servers, you may need to provide your own instance of Swagger2Customizer JPU> [3], [4] which allows to transform the OpenAPI/Swagger on the fly. Please JPU> let me know if that would it work for you, thank you. JPU> [1] JPU> https://docs.oracle.com/javaee/7/api/javax/ws/rs/container/DynamicFeature.html JPU> [2] JPU> https://aredko.blogspot.com/2016/02/your-jax-rs-apis-were-not-born-equal.html JPU> [3] JPU> https://cxf.apache.org/javadoc/latest/org/apache/cxf/jaxrs/swagger/Swagger2Customizer.html JPU> [4] https://cxf.apache.org/docs/swagger2feature.html (has customizer JPU> property) JPU> Best Regards, JPU> Andriy Redko >> Hi Andriy, >> I am again getting into trouble with server endpoint declarations. Now >> 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}/custo >> 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 >> 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 <drr...@gmail.com> >>> Sent: dinsdag 14 juni 2022 1:08 >>> To: Jean Pierre URKENS <jean-pierre.urk...@devoteam.com>; >>> iss...@cxf.apache.org; dev@cxf.apache.org >>> Subject: Re: JAXRS server endpoint not gracefully shutdown Hi Jean, >>> Indeed, the jaxrs:server does not expect address to be omitted, you >>> could use the "/" (and I believe an empty string would also make it): >>> <jaxrs:server id="restServer" basePackages="xxx" address="/"> ... >>> </jaxrs:server> >>> Thank you. >>> Hope it helps. >>> Best Regards, >>> Andriy Redko >>>> I create a JAXRS server endpoint (CXF 3.5.2) using spring bean >>>> declarations >>>> like: >>>> <jaxrs:server id="restServer" basePackages="xxx"> >>>> <jaxrs:serviceBeans> >>>> <ref bean="TestApi" /> >>>> </jaxrs:serviceBeans> >>>> <jaxrs:providers> >>>> <…/> >>>> </jaxrs:providers> >>>> <jaxrs:features> >>>> <… /> >>>> </jaxrs:features> >>>> <jaxrs:inInterceptors> >>>> <… /> >>>> </jaxrs:inInterceptors> >>>> <jaxrs:outInterceptors>* >>>> <**…**/>* >>>> </jaxrs:outInterceptors>* >>>> </jaxrs:server> >>>> Here my “TestApi” bean interface is declared like: >>>> @Path("accounts") >>>> @Consumes(MediaType.*APPLICATION_JSON*) >>>> @Produces(MediaType.*APPLICATION_JSON*) >>>> public interface TestApi { >>>> … >>>> } >>>> And CXF is triggered via a servlet configuration like: >>>> <servlet> >>>> <display-name>CXF Servlet</display-name> >>>> <servlet-name>CXFServlet</servlet-name> >>>> <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servle >>>> t -class>>>>> >>>> </servlet> >>>> <servlet-mapping> >>>> <servlet-name>CXFServlet</servlet-name> >>>> <url-pattern>/services/*</url-pattern> >>>> </servlet-mapping> >>>> Because I’ve got the @Path declaration on the interface type I’ve >>>> omitted the address=”accounts” attribute on the jaxrs:server >>>> declaration since otherwise I noticed that the server would be >>>> listening to /basepath/services/ accounts/accounts/…). >>>> Now this configuration works perfectly, only when shutting down the >>>> application server cxf calls >>>> ServerImpl#destroy() >>>> which delegates (via Obeservable) to >>>> AbstractHTTPDestination#deactivate() >>>> which calls >>>> registry.removeDestination(path). >>>> This path is null (no ‘address’ specified on jaxrs:server >>>> declaration) and results in a NPE on the registry Map. >>>> This causes an unclean shutdown of my server. >>>> Is this an error in cxf or is my jaxrs:server configured incorrectly? >>>> How does the ‘address’ attribute on the jaxrs:server declaration >>>> correctly interact with the @Path parameter on the API interface?