Setting SO_TIMEOUT for Webservice consumer in mule - mule

We are using webservice consumer to hit a service hosted by 3rd party.
While hitting the service, SocketTimeOutException happens after 16 minutes.
Our webservice consumer config is as given below.
<ws:consumer-config name="config_name"
wsdlLocation="${wsdlLocation}"
service="Service_name" port="service_portType"
serviceAddress="${serviceAddress}"
doc:name="Web Service Consumer" />
<ws:consumer config-ref="config_name" operation="test_operation"
doc:name="do_it" />
We have a default response timeout set at top of the configuration file.
<configuration defaultResponseTimeout="1000000" doc:name="Configuration" />
Now, when we asked the 3rd party about the time out, they asked us to set the SO_TIMEOUT of server to 0.
I know we can set it for https:connector with property 'serverSoTimeout="0"'.
My question is how do we set it for Webservice consumer?

This can be set by adding a parameter to your webservice endpoint like this:
http://hostname:port/restoftheendpoint?responseTimeout=120000
Or
This can be set up on the http listener global configuration attached to your wsconsumer config as below:
<ws:consumer-config name="test" wsdlLocation="test.wsdl" service="test" port="testSoap" serviceAddress="${test.endpoint}" doc:name="Web Service Consumer" connectorConfig="HTTP_Request_Config" />
<http:request-config name="HTTP_Request_Config" host="test" port="2000" responseTimeout="30000" doc:name="HTTP Request Configuration">
</http:request-config>

Related

Https soap service in mule

I have a requirement where soap based service needs to be consumed and in order to achieve that I had used WSConsumer component in Mule.
Where we give the service URL in the properties file and refer to it.
<ws:consumer-config name="Web_Service_Consumer" wsdlLocation="serviceApi.wsdl"
service="serviceAPI" port="serviceApiSoap12Port" serviceAddress="${serviceurl}"
doc:name="Web Service Consumer"/>
Now after the development we came to know that QA web service is a HTTPS web service and while hitting the service following exception is received
SSLHandshakeException: General SSLEngine problem
I'm able to hit the service with Http:request connector as following
<http:request-config name="HTTP_Request_Configuration" host="${host}" port="${port}"
doc:name="HTTP Request Configuration" protocol="HTTPS">
<tls:context>
<tls:trust-store insecure="true" />
</tls:context>
</http:request-config>
But the issue with above config is it won't work for HTTP configuration.
I should be able to connect to both HTTP & HTTPS as I have different environments.
Is there a way where I can achieve this with ws:consumer??
I assume the HTTP connector configuration shown is the one queried by your WS Consumer connector. A simple solution would be to configure the protocol of your HTTP config via property file but Mule doesn't play well with it because you may end-up with a TLS Context configured with HTTP and your connector won't work. There is a little trick you can do however: create 2 HTTP configurations - one for HTTP and one for HTTPS:
<http:listener-config name="HTTPS_Config"
protocol="HTTPS"
host="${host}"
port="${port}"
doc:name="HTTPS Config" >
<tls:context>
<tls:key-store type="${keystore.type}"
path="${keystore.path}"
keyPassword="${keystore.keyPassword}"
password="${keystore.password}"/>
</tls:context>
</http:listener-config>
<http:listener-config name="HTTP_Config"
host="${host}"
port="${port}"
doc:name="HTTP Config" >
</http:listener-config>
In a property file, define which configuration (i.e. which protocol) should be used:
host=localhost
port=443
protocol=HTTPS # or HTTP
And finally in your flow, use your property to reference the proper HTTP(S) config:
<flow name="http-testFlow">
<http:listener config-ref="${protocol}_Config" path="/test" doc:name="HTTP"/>
...
</flow>
The trick is to name your configuration ${protocol}_Config such as HTTP_Config and HTTPS_Config so the proper one is used at runtime via config-ref="${protocol}_Config". Mule will then dynamically use the proper configuration when your app is launched. This is entirely transparent for the user as only the protocol (HTTP vs. HTTPS) needs to be configured, and it can be used in any environment.
You can use this differently, the idea is to have Mule pick your HTTP or HTTPS dynamically at runtime.
EDIT: to configure your WS Consumer with HTTPS you'll need to reference a proper HTTP Requester Configuration such as:
<ws:consumer-config name="Web_Service_Consumer"
...
connectorConfig="HTTP_Request_Configuration"/>
<http:request-config name="HTTP_Request_Configuration"
...
<tls:context>
...
</tls:context>
...
/>
See Web Service Consumer documentation for details.
Note: though this solution works I would recommend using HTTPS all the time, for security reasons and to have less differences between your dev/QA/Prod/... environments - among other things.
I faced similar issues, we finally chose to have only an HTTPS config and define via property which keystore to use at runtime. In dev we would use a self-signed certificate and a proper keystore in environments requiring proper security.
Hope this helps.

Mule HTTPS request with Basic authentication

I am trying to make an HTTPS request in Mule with Basic Authentication. For some reason I only have NTML and None as options in the HTTP connector.
So I tried adding the basic-authentication element to my request-config:
<http:request-config name="Req_My" protocol="HTTPS" host="${my.host}" port="${my.port}" doc:name="HTTP Request Configuration">
<http:basic-authentication username="${my.user}" password="${my.password}" preemptive="true" />
</http:request-config>
But no Authorization header is set in the debug output.
I could always do a set Property (if I find out how to do a Mel Base64 encode) but according to the documentation the Basic authentication is standard functionality

Migrating to the New HTTP Connector

I've upgraded from Mule 3.3.x to 3.6.x and since the old http endpoint is deprecated in 3.6.x I wanted to migrate to the new HTTP connector.
Here is the original code for calling a webservice and healthcheck
Webservice
<http:outbound-endpoint connector-ref="NoSessionConnector"
address="${testmigrationapp.endpoint.url}"
responseTimeout="${testmigrationapp.endpoint.timeout}" keep-alive="true"
responseTransformer-refs="errorHandler">
<jms:transaction action="ALWAYS_JOIN"/>
Healthcheck
<http:inbound-endpoint exchange-pattern="request-response" address="${testmigrationapp.healthcheck.address}" doc:name="HTTP"/>
How would I implement this using the new HTTP connector?
Thanks
An HTTP outbound endpoint would translate to an HTTP request. You will need to define a request-config specifying the host, port and persistent connections (because of the keep-alive=true). Then you can replace the outbound endpoint with a request element specifying the URL path and the response timeout. For example:
<http:request-config name="persistentRequestConfig" usePersistentConnections="true" host="example.com" port="80" />
<flow name="persistent">
<http:request config-ref="persistentRequestConfig" path="/" responseTimeout="30" />
</flow>
An HTTP inbound endpoint would translate to an HTTP listener. You will need to define a listener-config specifying the host and port. Then you can replace the inbound endpoint for a listener element specifying the URL path. For example:
<http:listener-config name="listenerConfig" host="0.0.0.0" port="8081"/>
<flow name="testFlow">
<http:listener config-ref="listenerConfig" path="/"/>
<echo-component/>
</flow>
For more details you can checkout our docs regarding the migration.

mule asynchronous tls/ssl inbound endpoint

I'm working on a project where one of the requirements is to connect to a server using ssl/tls and subscribe to messages. I have setup a tls outbound-endpoint and can connect to the server. I have a spring bean that performs custom handshaking and part of that is subscribing to content from the server. Once subscribed I should receive messages asynchronously without having to poll for them. Is there a way to do this in Mule 3.3? Thanks for the help.
It seems you have a specific use case in which you can't use HTTPS. Mule does provide support for TCP connection, but I couldn't find the option to make the the secure TCP connection (which I beleive will be over SSL).
You can always write your custom endpoint connector code in a java component and call that java component using Quartz (for polling)
<flow name="polling-flow" doc:name="polling-flow">
<quartz:inbound-endpoint jobName="polling"
repeatInterval="5000" responseTimeout="10000" doc:name="Quartz">
<quartz:event-generator-job>
<quartz:payload>call-custom-component-to-poll-secure-tcp</quartz:payload>
</quartz:event-generator-job>
</quartz:inbound-endpoint>
<component doc:name="Java" class="com.company.CustomSecureTCPCode"></component>
<!-- do whatever you want to with the payload received from calling the endpoint -->
</flow>
I used a quartz inbound endpoint and setup an endpoint polling job and polled my endpoint. See the config below:
<flow name="QuartzPollingFlow">
<quartz:inbound-endpoint repeatCount="-1" repeatInterval="1000" jobName="myPoller">
<quartz:endpoint-polling-job>
<quartz:job-endpoint timeout="300" ref="SecureTcpEndpoint"/>
</quartz:endpoint-polling-job>
</quartz:inbound-endpoint>
<flow-ref name="ProcessingFlow"/>
</flow>

Why won't a REST component not receive a call made internal to an app when multiple Global HTTP Connectors are Configured?

I'm struggling to configure and deploy to CloudHub an app with multiple Global HTTP Connectors and a REST component.
My application has two flows: one polls an RSS feed for news and posts a json representation of that feed to an http inbound endpoint in the same app (endpoint resides on second flow). The second flow receives that post, does some magic, including persisting the item to storage, and then notifies via an http outbound endpoint an external node.js web app to push the item via web sockets to active clients.
I have tried what feels like dozens of different configurations involving a variety of HTTP Global Connectors and http in and outbound endpoints, but I can't get everything to work. I currently have:
A Polling HTTP Connector
An HTTP endpoint referencing above polling http connector to get RSS Feed
One Global Connector (we'll call HTTP_ONE) to receive messages at localhost:${http.port}
An http oubound endpoint configured referencing HTTP_ONE and configured to post an activity to /api/v1/activity
An http inbound endpoint configured to receive messages for /api/v1 and a Jersey controller sitting just behind this endpoint which takes /activity.
Another Global Connector (HTTP_TWO) with an external host set as the proxy host name (e.g. somehost.somewhere.com).
An http outbound endpoint configured to post messages to somehost.somewhere.com
On my localhost, I've had to use various properties to allow for all of this activity on multiple ports on my laptop.
On CloudHub, I'm using localhost and ${http.port} everywhere except in the oubound endpoint that calls to an external web service.
I can get one flow or the other working, but not both.... My problem seems to be with the posting a given news item from the RSS feed to the Inbound HTTP Endpoint. It is sending the post to http://localhost:80/api/v1/activity, but the connector says that no such path exists (it only lists /api/v1 as an option), which makes me think that the call is not getting as far as the Jersey Controller which sits behind the Global Connector and the http inbound endpoint for /api/v1/activity. Is this behavior an inherent flaw in using the REST Component and multiple global http connectors? Also, why do we have to reference a Global HTTP Connector when making an outbound call? Why can't we use the default HTTP Connector? (Maybe the last two questions should go in a subsequent post...)
Here's most of the relevant config for the two flows:
Global Connectors
<http:polling-connector name="PollingHttpConnector" pollingFrequency="60000" doc:name="HTTP Polling" clientSoTimeout="10000" cookieSpec="netscape" receiveBacklog="0" receiveBufferSize="0" sendBufferSize="0" serverSoTimeout="10000" socketSoLinger="0" validateConnections="true"/>
<http:connector name="EduStream_HTTP" cookieSpec="netscape" validateConnections="true" sendBufferSize="0" receiveBufferSize="0" receiveBacklog="0" clientSoTimeout="10000" serverSoTimeout="10000" socketSoLinger="0" proxyHostname="${edustream.host}" doc:name="HTTP\HTTPS" proxyPort="80"/>
<http:connector name="EduStreamESB_HTTP" cookieSpec="netscape" validateConnections="true" sendBufferSize="0" receiveBufferSize="0" receiveBacklog="0" clientSoTimeout="10000" serverSoTimeout="10000" socketSoLinger="0" proxyHostname="localhost" proxyPort="${http.port}" doc:name="HTTP\HTTPS"/>
News RSS Feed Flow
<flow name="ucdNewsConsumer" doc:name="ucdNewsConsumer">
<http:inbound-endpoint address="http://news.ucdavis.edu/xml/getnews.php/rss/category/General%20Interest"
connector-ref="PollingHttpConnector" doc:name="HTTP" exchange-pattern="one-way"/>
<rss:feed-splitter/>
<rss:entry-last-updated-filter/>
<component class="edu.ucdavis.edustream.esb.news.rss.EntryReceiver" doc:name="Java"/>
<logger message="#[payload]" level="INFO" doc:name="Logger"/>
<http:outbound-endpoint exchange-pattern="request-response" host="localhost" port="${http.port}" path="api/v1/activity" doc:name="HTTP" mimeType="application/json" connector-ref="EduStreamESB_HTTP" />
<logger message="Payload is: #[payload] Inbound Headers: #[headers:INBOUND:*] Outbound Headers: #[headers:OUTBOUND:*] Exception is: #[exception]" level="INFO" doc:name="Logger"/>
</flow>
Activity Publication Service -- Core Flow
<flow name="edustreamesbFlow1" doc:name="edustreamesbFlow1">
<http:inbound-endpoint exchange-pattern="request-response" host="localhost" port="${http.port}" doc:name="HTTP" contentType="application/json" mimeType="application/json" path="api/v1" connector-ref="EduStreamESB_HTTP"/>
<jersey:resources doc:name="REST">
<component class="edu.ucdavis.edustream.esb.activity.restapi.ActivityController"/>
</jersey:resources>
<component class="edu.ucdavis.edustream.esb.activity.restapi.JerseyResponseTransformer" doc:name="JerseyRespTrans"/>
<flow-ref name="PublishActivity" doc:name="Publish Activity"/>
</flow>
<sub-flow name="PublishActivity" doc:name="PublishActivity">
<component doc:name="ActivityService">
<spring-object bean="activityService"/>
</component>
<logger message="#[payload] #[message]" level="INFO" doc:name="Logger"/>
<http:outbound-endpoint exchange-pattern="request-response" host="${edustream.host}" port="80" path="api/v1/activity" mimeType="application/json" contentType="application/json" doc:name="HTTP" connector-ref="EduStream_HTTP"/>
</sub-flow>
I do not get why proxyHostname and proxyPort are configured on both EduStream_HTTP and EduStreamESB_HTTP connectors while the HTTP endpoints from these connectors target the same host/port as their destination address. This doesn't make any sense to me.
Are you really sure you need to use proxies?
For EduStreamESB_HTTP the answer is clearly no: you're calling CloudHub from CloudHub, so no need for a proxy.
For EduStreamESB_HTTP, maybe... but that still seems very strange.