[ https://issues.apache.org/jira/browse/GEODE-8372?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17167698#comment-17167698 ]
ASF GitHub Bot commented on GEODE-8372: --------------------------------------- demery-pivotal commented on a change in pull request #5411: URL: https://github.com/apache/geode/pull/5411#discussion_r462585646 ########## File path: geode-management/src/main/java/org/apache/geode/management/api/RestTemplateClusterManagementServiceTransport.java ########## @@ -73,6 +75,27 @@ public RestTemplateClusterManagementServiceTransport(RestTemplate restTemplate) { this.restTemplate = restTemplate; this.restTemplate.setErrorHandler(DEFAULT_ERROR_HANDLER); + + // configur the rest template to use a speciic jackson converter + List<HttpMessageConverter<?>> messageConverters = restTemplate.getMessageConverters(); + MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = messageConverters.stream() + .filter(MappingJackson2HttpMessageConverter.class::isInstance) + .map(MappingJackson2HttpMessageConverter.class::cast) + .findFirst().orElse(null); + + if (jackson2HttpMessageConverter == null) { + jackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter(); + messageConverters.add(jackson2HttpMessageConverter); + } + + jackson2HttpMessageConverter.setPrettyPrint(false); + // the client should use a mapper that would ignore unknown properties in case the server + // is a newer version than the client + jackson2HttpMessageConverter + .setObjectMapper(GeodeJsonMapper.getMapperIgnoringUnknownProperties()); + // if we don't set the default charset here, the request will use ServletRequest's default + // charset which is ISO-8859 Review comment: I think this comment is overly specific. If we don't set the charset, the request will use some default, but it may not be ISO-8859. I've been able to change the default on my Mac and in docker images by: - setting the `LC_ALL` shell variable. - specifying the `file.encoding` JVM option (which I think overrides `LC_ALL`, but I'm not sure). Consider removing the comment. To me, `setDefaultCharset(UTF_8)` is clear enough without it. But if you want a comment, consider: "... which may not be UTF-8." ---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: us...@infra.apache.org > Configure CMS to send UTF-8 regardless of JVM default > ----------------------------------------------------- > > Key: GEODE-8372 > URL: https://issues.apache.org/jira/browse/GEODE-8372 > Project: Geode > Issue Type: Bug > Components: management > Reporter: Dale Emery > Priority: Major > Labels: GeodeOperationAPI, pull-request-available > > In a client, CMS accepts only UTF-8 messages from the locator. But the > locator can send non-UTF-8 messages depending on how the JVM and OS are > configured. > It looks as if the locator CMS uses the JVM's default character encoding, and > the JVM sets its default character encoding based on the operating system's > default locale. > If a client CMS accepts only UTF-8, the locator CMS should send only UTF-8, > regardless of the JVM's default character encoding. > Example: I have a test client that uses a {{ClientClusterManagementService}} > to create a region. The locator, runs on a machine where the default locale > is us_EN.US-ASCII, sends US-ASCII responses. The client throws an > {{UnknownContentTypeException}}: > {noformat} > org.springframework.web.client.UnknownContentTypeException: Could not extract > response: no suitable HttpMessageConverter found for response type [class > org.apache.geode.management.api.ClusterManagementRealizationResult] and > content type [application/json;charset=US-ASCII] > at > org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:126) > ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE] > at > org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:998) > ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE] > at > org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:981) > ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE] > at > org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:741) > ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE] > at > org.springframework.web.client.RestTemplate.execute(RestTemplate.java:674) > ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE] > at > org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:583) > ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE] > at > org.apache.geode.management.api.RestTemplateClusterManagementServiceTransport.create(RestTemplateClusterManagementServiceTransport.java:248) > ~[geode-management-1.12.0.jar:na] > at > org.apache.geode.management.api.RestTemplateClusterManagementServiceTransport.submitMessage(RestTemplateClusterManagementServiceTransport.java:153) > ~[geode-management-1.12.0.jar:na] > at > org.apache.geode.management.internal.ClientClusterManagementService.create(ClientClusterManagementService.java:64) > ~[geode-management-1.12.0.jar:na] > at > org.apache.geode.kubernetes.client.service.AsyncOperationService.createRegion(AsyncOperationService.java:46) > ~[main/:na] > at > org.apache.geode.kubernetes.client.api.Controller.createRegion(Controller.java:27) > ~[main/:na] > at > java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native > Method) ~[na:na] > at > java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) > ~[na:na] > at > java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) > ~[na:na] > at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na] > at > org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190) > ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE] > at > org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138) > ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE] > at > org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105) > ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE] > at > org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:879) > ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE] > at > org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793) > ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE] > at > org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) > ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE] > at > org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) > ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE] > at > org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) > ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE] > at > org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) > ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE] > at > org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) > ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE] > at javax.servlet.http.HttpServlet.service(HttpServlet.java:634) > ~[tomcat-embed-core-9.0.36.jar:9.0.36] > at > org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) > ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE] > at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) > ~[tomcat-embed-core-9.0.36.jar:9.0.36] > at > org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) > ~[tomcat-embed-core-9.0.36.jar:9.0.36] > at > org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) > ~[tomcat-embed-core-9.0.36.jar:9.0.36] > at > org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) > ~[tomcat-embed-websocket-9.0.36.jar:9.0.36] > at > org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) > ~[tomcat-embed-core-9.0.36.jar:9.0.36] > at > org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) > ~[tomcat-embed-core-9.0.36.jar:9.0.36] > at > org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) > ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE] > at > org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) > ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE] > at > org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) > ~[tomcat-embed-core-9.0.36.jar:9.0.36] > at > org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) > ~[tomcat-embed-core-9.0.36.jar:9.0.36] > at > org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) > ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE] > at > org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) > ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE] > at > org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) > ~[tomcat-embed-core-9.0.36.jar:9.0.36] > at > org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) > ~[tomcat-embed-core-9.0.36.jar:9.0.36] > at > org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) > ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE] > at > org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) > ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE] > at > org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) > ~[tomcat-embed-core-9.0.36.jar:9.0.36] > at > org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) > ~[tomcat-embed-core-9.0.36.jar:9.0.36] > at > org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) > ~[tomcat-embed-core-9.0.36.jar:9.0.36] > at > org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) > ~[tomcat-embed-core-9.0.36.jar:9.0.36] > at > org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) > ~[tomcat-embed-core-9.0.36.jar:9.0.36] > at > org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) > ~[tomcat-embed-core-9.0.36.jar:9.0.36] > at > org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) > ~[tomcat-embed-core-9.0.36.jar:9.0.36] > at > org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) > ~[tomcat-embed-core-9.0.36.jar:9.0.36] > at > org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) > ~[tomcat-embed-core-9.0.36.jar:9.0.36] > at > org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373) > ~[tomcat-embed-core-9.0.36.jar:9.0.36] > at > org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) > ~[tomcat-embed-core-9.0.36.jar:9.0.36] > at > org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) > ~[tomcat-embed-core-9.0.36.jar:9.0.36] > at > org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590) > ~[tomcat-embed-core-9.0.36.jar:9.0.36] > at > org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) > ~[tomcat-embed-core-9.0.36.jar:9.0.36] > at > java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) > ~[na:na] > at > java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) > ~[na:na] > at > org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) > ~[tomcat-embed-core-9.0.36.jar:9.0.36] > at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na] > {noformat} > For testing: On my mac, it's possible to set the encoding for a locator by > setting the {{LC_ALL}} environment variable in the shell before launching the > locator. > For example, if I execute {{export LC_ALL=en_US.US-ASCII}}, then launch a > locator in that shell, the locator sends CMS messages in US-ASCII, as shown > in this {{curl -v}} output: > {noformat} > % curl localhost:7070/management/v1/regions -v > * Trying ::1... > * TCP_NODELAY set > * Connected to localhost (::1) port 7070 (#0) > > GET /management/v1/regions HTTP/1.1 > > Host: localhost:7070 > > User-Agent: curl/7.64.1 > > Accept: */* > > > < HTTP/1.1 200 OK > < Date: Tue, 21 Jul 2020 16:28:26 GMT > < Content-Type: application/json; charset=US-ASCII > < X-Content-Type-Options: nosniff > < X-XSS-Protection: 1; mode=block > < Cache-Control: no-cache, no-store, max-age=0, must-revalidate > < Pragma: no-cache > < Expires: 0 > < X-Frame-Options: DENY > < Content-Length: 31 > < Server: Jetty(9.4.21.v20190926) > < > * Connection #0 to host localhost left intact > {"statusCode":"OK","result":[]}* Closing connection 0 > {noformat} -- This message was sent by Atlassian Jira (v8.3.4#803005)