How to overcome Invalid token character caused by Content-Type=[text/xml; subtype=gml/2.1.2] in Spring HttpMessageConverterExtractor?

最后都变了- 提交于 2019-12-25 08:25:13

问题


I'm stuck at exception

java.lang.IllegalArgumentException: Invalid token character '/' in token "gml/2.1.2"
at org.springframework.http.MediaType.checkToken(MediaType.java:354)

I'm using Spring Integration 3.0 RC1 and http outbound gateway to send request to Geoserver. Unfortunately the exception is thrown from inside of org.springframework.web.client.RestTemplate which I cannot override (outbound gateway manages it), so it's to deep for me to change the headers by some HeaderMapper as I've already tried. I'm also unable to change the request header coming from external site, as it's produced by Geoserver.

The error cause header is: Content-Type=[text/xml; subtype=gml/2.1.2]

Please give me some clues if you have one, I'm struggling with it for several days now.

My spring integration setup:

<util:list id="wfsProxyMessageConverterList">
    <bean class="xxx.StringWfsHttpMessageConverter" />
    <bean class="xxx.ByteArrayWfsHttpMessageConverter" />       
</util:list>

<int:channel id="wfsRequest"></int:channel>
<int:channel id="wfsResponse"></int:channel>

<bean id="wfsHeaderMapper" class="xxx.WfsHeaderMapper" />

<int-http:inbound-gateway id="wfsInboundGateway" supported-methods="POST"
    request-channel="wfsRequest" reply-channel="wfsResponse"
    path="/gisproxy/wfs" reply-timeout="10000"  
    header-mapper="wfsHeaderMapper"         
        message-converters="wfsProxyMessageConverterList"

    />

<int-http:outbound-gateway id="wfsOutboundGateway"
    request-channel="wfsRequest" reply-channel="wfsResponse"
    url="#{geoserverConfig.url}/wfs"
    http-method="POST" charset="UTF-8" reply-timeout="10000"
    expected-response-type="java.lang.String"
    message-converters="wfsProxyMessageConverterList"
    header-mapper="wfsHeaderMapper"

    encode-uri="false" request-factory="apacheCommonsHttpClient">               
</int-http:outbound-gateway>

Cheers, denu

--- edit: added stack trace ---

SEVERE: Servlet.service() for servlet [core] in context with path [/myapp] threw exception [Request processing failed; nested exception is org.springframework.integration.MessageHandlingException: HTTP request execution failed for URI [https://xx.xxx.xxx.xx:8181/geoserver/wfs]] with root cause
java.lang.IllegalArgumentException: Invalid token character '/' in token "gml/2.1.2"
at org.springframework.http.MediaType.checkToken(MediaType.java:354)
at org.springframework.http.MediaType.checkParameters(MediaType.java:374)
at org.springframework.http.MediaType.<init>(MediaType.java:335)
at org.springframework.http.MediaType.parseMediaType(MediaType.java:722)
at org.springframework.http.HttpHeaders.getContentType(HttpHeaders.java:305)
at org.springframework.web.client.HttpMessageConverterExtractor.getContentType(HttpMessageConverterExtractor.java:113)
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:84)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:687)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:673)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:491)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:460)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:409)
at org.springframework.integration.http.outbound.HttpRequestExecutingMessageHandler.handleRequestMessage(HttpRequestExecutingMessageHandler.java:372)
at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:142)
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:73)
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:115)
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:102)
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:77)
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:178)
at org.springframework.integration.core.MessagingTemplate.doSend(MessagingTemplate.java:304)
at org.springframework.integration.core.MessagingTemplate.doSendAndReceive(MessagingTemplate.java:335)
at org.springframework.integration.core.MessagingTemplate.sendAndReceive(MessagingTemplate.java:255)
at org.springframework.integration.gateway.MessagingGatewaySupport.doSendAndReceive(MessagingGatewaySupport.java:234)
at org.springframework.integration.gateway.MessagingGatewaySupport.sendAndReceiveMessage(MessagingGatewaySupport.java:208)
at org.springframework.integration.http.inbound.HttpRequestHandlingEndpointSupport.actualDoHandleRequest(HttpRequestHandlingEndpointSupport.java:478)
at org.springframework.integration.http.inbound.HttpRequestHandlingEndpointSupport.doHandleRequest(HttpRequestHandlingEndpointSupport.java:380)
at org.springframework.integration.http.inbound.HttpRequestHandlingMessagingGateway.handleRequest(HttpRequestHandlingMessagingGateway.java:101)
at org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter.handle(HttpRequestHandlerAdapter.java:49)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:920)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:827)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:647)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:801)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:183)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.springframework.orm.hibernate4.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:152)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)

回答1:


According to RFC 2616 (and as Taylor said according to RFC 1341) it is an invalid value for Content-Type HTTP header. So you should have deal with Geoserver anyway.

However, let's try to find a workaround to make your application working.

You have gone with right way using a custom implementation of DefaultHttpHeaderMapper. In this case you should exclude Content-Type header from inbound mapping - DefaultHttpHeaderMapper#setInboundHeaderNames - list all desired HTTP header name, but not Content-Type. You can see all supported headers from DefaultHttpHeaderMapper.HTTP_REQUEST_HEADER_NAMES constant (source code).

Then you should override DefaultHttpHeaderMapper#toHeaders, invoke super.toHeaders and take care of Content-Type, but using HttpHeaders.getFirst("Content-Type")

Of course, those all are needed, if you really are interested in Content-Type. If not, it's just enough to provide mapped-request-headers attribute with others headers names, or just a trick - mapped-request-headers="-" to suppress all request headers.




回答2:


I came up with this solution:

class WfsRestTemplate extends RestTemplate {
    @Override
    protected <T> T doExecute(URI url, HttpMethod method, RequestCallback callback, final ResponseExtractor<T> responseExtractor) throws RestClientException {
        return super.doExecute(url, method, callback, response -> {
            String contentType = response.getHeaders().getFirst("Content-Type");
            if (contentType.startsWith("text/xml")) response.getHeaders().setContentType(MediaType.TEXT_XML);
            return responseExtractor.extractData(response);
        });
    }
}


来源:https://stackoverflow.com/questions/20508804/how-to-overcome-invalid-token-character-caused-by-content-type-text-xml-subtyp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!