tisdag 21 januari 2014

Quick tip: Howto get rid of REST client failed to route to service, Socket connection closed or Http Headers too large.

A common issue during development of a Mule RESTful webservice client is that calls to the service is denied with error messages similar to "Failed to route..." or "java.net.SocketException: Connection reset" although you have specified correct endpoint address in your <http:outbound-endpoint>.

If the REST service in fact is not called (check with logging or breakpoint) and a traffic analyser like Wireshark or similar tells you its a HTTP "Bad request" or similar allthough the TCP traffic looks correct, you might have an issue with your HTTP headers.

In fact this is quite often related to the fact that Mule by default automatically transforms Mule headers to HTTP headers in the transport and vice versa. This is a very nice feature if you need to for example call a REST service and still keep sessionid or if splitted data is sent to the service for each item and you need to keep correlationids to perform aggregations on the result data further down the flow.
However the MULE_SESSION header is quite large and different vendors of different application servers like JBoss or Tomcat has different settings on maximum allowed sizes of the headers although the HTTP specs has no such limitation. This is often what causes the request to become a "Bad request" i.e to large headers.

The tip of the day is hence to set up a global connector which configures inbound or outbound endpoints to use a NullSessionHandler simply by overriding the default sessionHandler like this:

 <http:connector name="ConnectorWithoutMuleSession" doc:name="HTTP/HTTPS_Nosession">  
           <service-overrides sessionHandler="org.mule.session.NullSessionHandler"/>  
 </http:connector>  

In your flow you can now reference this connector either from an outbound endpoint which will avoid sending the MULE_SESSION header or on an inbound endpoint which will avoid processing the MULE_SESSION header on incoming messages.

Like this:

 <http:outbound-endpoint method="GET" exchange-pattern="request-response" address="${flow.myserviceurl}" contentType="application/json" doc:name="HTTP_out" connector-ref="ConnectorWithoutMuleSession"/>

3 kommentarer:

  1. This is indeed a nice tip.

    However be aware that if/when you explicitly define a connector it will be used as the default connector even if you do not specify a connector-ref on the endpoint. This could be a problem if you for example have multiple http outbound endpoints and you want to send the X-MULE_SESSION header to some but not to others. You will then have to define two connectors one with service overrides and one without.

    Also even if the mule session object is not send with the NullSessionHandler MuleESB 3.4.0 CE will still send a empty X-MULE_SESSION header. Some servers (like early versions of JBossESB) does NOT like empty headers. Also MuleESB still leaks other HTTP headers X-MULE*.

    Cheers
    Pontus

    SvaraRadera
  2. That is indeed valuable input on the matter Pontus.

    Thank you!

    SvaraRadera
  3. Hi Jon,
    This service override doesn't work in new mule http listener connector. Any idea how to implement this service override in new Mule Http connector (3.7.3) ?
    thanks

    SvaraRadera