Setting http headers processor:http-client - spring-xd

I would like to set User-Agent header when using processor:http-client
I see there is mappedRequestHeaders option, but how to use to set User-Agent: Mozilla for example
Either I am missing something or spring-xd lacking processor:header-enricher. This would do what I am looking for in regular Spring Integration context:
<int:chain id="mychain" input-channel="http-request-data">
<int:header-enricher>
<int:header name="User-Agent" value="curl/7.0.48"/>
</int:header-enricher>
<int-http:outbound-gateway url="${url}" http-method="GET" expected-response type="java.lang.String"/>
<int-file:outbound-channel-adapter directory="${output-folder}" filename-generator-expression="'${filename}'" />
</int:chain>

The <int-http:outbound-gateway> has request-factory attribute and can inject to it HttpComponentsClientHttpRequestFactory bean. This ClientHttpRequestFactory provides some default User-Agent header value.
Since it is your own Spring XD instance you can modify an existing [XD_HOME]\xd\modules\processor\http-client\config\http-client.xml adding that bean definition:
<bean id="requestFactory" class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory"/>
<int-http:outbound-gateway request-factory="requestFactory"/>
Leaving everything other without changes.
In addition you should add org.apache.httpcomponents:httpclient:4.3.5 jar to the lib of that http-client module.
The Commons HttpClient allows even to specify httpclient.useragent System property to override the default value.
Feel free to raise (https://jira.spring.io/browse/XD) an issue regarding processor:header-enricher.
Of course you can overcome it right now with the Groovy script processor:
org.springframework.integration.support.MessageBuilder.withPayload(payload)
.copyHeaders(headers)
.setHeader('User-Agent', 'curl/7.0.48')
.build()
HTH

Groovy script approach is nice.. for now I added processor/header.xml : Groovy script approach is nice.. for now I added processor/header.xml - very simple I only needer one header
<channel id="input"/>
<header-enricher input-channel="input" output-channel="output">
<header name="${name}" value="${value}"/>
</header-enricher>
<channel id="output"/>

Related

Missing soap action :: Spring Integration

I am working on a spring integration component where I posting data to external third-party URL. and Its is working fine with the below code.
<!-- language: lang-xml -->
<int:chain id="channe.id"
input-channel="request.in"
output-channel="reply.channel">
<int-ws:header-enricher>
<int-ws:soap-action
value="${service.soapaction}" />
</int-ws:header-enricher>
<int-ws:outbound-gateway
id="invoker.ws.outbound.gateway"
ignore-empty-responses="true" message-sender="message.sender"
interceptors="${SecurityInterceptor}"
message-factory="${mmessageFactory}"
uri="${protocol}://${host}:${port}/{endpoint}">
<int-ws:uri-variable name="endpoint"
expression="headers.endpoint" />
<int-ws:request-handler-advice-chain>
<ref bean="commonRetryAdviceBean" />
</int-ws:request-handler-advice-chain>
</int-ws:outbound-gateway>
</int:chain>
Below is payload received by third part api.
<MessageLogTraceRecord>
<HttpRequest xmlns="http://schemas.microsoft.com/2004/06/ServiceModel/Management/MessageTrace">
<Method>POST</Method>
<QueryString></QueryString>
<WebHeaders>
<Content-Length>9381</Content-Length>
<Content-Type>text/xml; charset=UTF-8</Content-Type>
<Accept>text/xml</Accept>
<Accept-Encoding>gzip</Accept-Encoding>
<Host>myhost</Host>
<User-Agent>Jakarta Commons-HttpClient/3.1</User-Agent>
<SOAPAction>"http://www.mysoap.com/action/update"</SOAPAction>
</WebHeaders>
Now, I have to add an additional security feature and send the API key in the HTTP header or soap header. SO I modified my code as below. Now I can see API key is sent as soap header but some how SOAPAction is going empty, not sure why.
below is the modified code to send api ket as part of soap header.
<int:chain id="channe.id"
input-channel="request.in"
output-channel="reply.channel">
<int-ws:header-enricher>
<int-ws:soap-action
value="${service.soapaction}" />
</int-ws:header-enricher>
<int-ws:outbound-gateway
id="invoker.ws.outbound.gateway"
ignore-empty-responses="true" message-sender="message.sender"
interceptors="${SecurityInterceptor}"
message-factory="${mmessageFactory}"
mapped-request-headers="soapHeaderMapper"
uri="${protocol}://${host}:${port}/{endpoint}">
<int-ws:uri-variable name="endpoint"
expression="headers.endpoint" />
<int-ws:request-handler-advice-chain>
<ref bean="commonRetryAdviceBean" />
</int-ws:request-handler-advice-chain>
</int-ws:outbound-gateway>
</int:chain>
<bean id="soapHeaderMapper"
class="org.springframework.integration.ws.DefaultSoapHeaderMapper">
<property name="requestHeaderNames">
<list>
<value>api-key</value>
</list>
</property>
</bean>
After adding mapped-request-headers now I am getting
org.springframework.messaging.MessagingException: The message could not be processed because the action '' is invalid or unrecognized.; nested exception is org.springframework.ws.soap.client.SoapFaultClientException: The message could not be processed because the action '' is invalid or unrecognized., failedMessage=GenericMessage
when I checked the payload received by thirdparty api I can see SOAP action is empty I am not sure why.
Please help me.
Thanks.
<QueryString></QueryString>
<WebHeaders>
<Content-Length>9463</Content-Length>
<Content-Type>text/xml; charset=UTF-8</Content-Type>
<Accept>text/xml</Accept>
<Accept-Encoding>gzip</Accept-Encoding>
<Host>myhost</Host>
<User-Agent>Jakarta Commons-HttpClient/3.1</User-Agent>
<SOAPAction>""</SOAPAction>
</WebHeaders>
</HttpRequest>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<soapenv:Header api-key="dummy-123455555uuuuuuuuuuuqwert">
The mapped-request-headers="soapHeaderMapper" is wrong configuration. It is exactly about names, but in your case you try to make a reference to the DefaultSoapHeaderMapper bean definition.
Consider to use:
<xsd:attribute name="header-mapper">
<xsd:annotation>
<xsd:documentation>
Reference to a SoapHeaderMapper implementation
that this gateway will use to map between Spring Integration
MessageHeaders and the SoapHeader.
</xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.ws.SoapHeaderMapper"/>
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
instead.
Also there is the with your header names to map: when you configure some custom header names, all the standard headers are missed. So, alongside with the api-key, you need to consider include the mentioned ws_soapAction name as well.

Spring integration chain resolver service activator method

<int:chain input-channel="request" output-channel="response">
<int:service-activator method="create" ref="ServiceImpl" />
<int:service-activator method="update" ref="ServiceImpl" />
<int:service-activator method="cancel" ref="ServiceImpl" />
</int:chain>
So I'am learning spring integration, and ran into problem how to resolve which service method to call? I tried to use router and used expression:
<int:router input-channel="inputChannel" expression="payload.type">
<int:mapping value="CREATE" channel="create"/>
<int:mapping value="UPDATE" channel="update"/>
<int:mapping value="CANCEL" channel="cancel"/>
</int:router>
Maybe there is a way to solve it into chain?
Sorry, not clear what you are asking. The router is like an if...else to determine the next processing step according incoming data. The chain is like a public API which may call several methods: the next one is going to be called after the previous. Your how to resolve which service method to call somehow is not related to the chain at all. The router part is good one, but chain doesn't have any dynamic resolutions

Spring Integration Web Service Log SOAP Request Message (EVEN if the soap message is not correct)

Could you tell me the way to log the SOAP message of , even if the message is not correct format ?
<sws:interceptors>
<bean class="com.capgemini.manulife.integration.interceptor.LogInterceptor" />
</sws:interceptors>
<!-- inbound -->
<ws:inbound-gateway id="cas-inbound-gateway" request-channel="casRequestChannel" reply-channel="casResponseChannel"
marshaller="casMarshaller" unmarshaller="casMarshaller" />
<int:channel id="casRequestChannel">
<int:interceptors>
<int:wire-tap channel="SOAPLogChannel"/>
</int:interceptors>
</int:channel>
<int:channel id="SOAPLogChannel" />
<int:logging-channel-adapter id="logger" expression="payload" level="INFO" channel="SOAPLogChannel"/>
As you see, I already using PayloadLoggingInterceptor (LogInterceptor extends PayloadLoggingInterceptor ), but it did not go through PayloadLoggingInterceptor
Thank you and best regards,
It's not Spring Integration question, but more up to SOAP directly.
So, if your XML isn't with correct format, you don't have choice unless check it manually before unmarshalling.
So, you have to rely on the simple <ws:inbound-gateway> do the <int-xml:validating-filter> (or some other check) and only after that perform <int-xml:unmarshalling-transformer>.
Yes, we can add Filter to Spring Web Service using FilterRegistrationBean ^^

Appending X to Custom Request Headers in Spring-Integration

I found that when I want to make a REST call using Spring-Integration, it automatically appends 'x' in case its a custom header.
For example in Spring-integration while sending custom request headers such as API-KEY, the actual request header name in the API call becomes X-API-KEY and so it fails.
It seems like Spring is standardizing by enforcing the Custom request headers to start with X, is there a work around?
<int:channel id="requestChannel"/>
<int:channel id="httpHeaderEnricherChannel"/>
<int-http:outbound-gateway request-channel="requestChannel"
url="http://localhost:9090/balance"
http-method="GET"
mapped-request-headers="Api-Key"
expected-response-type="java.lang.String"/>
<int:header-enricher input-channel="httpHeaderEnricherChannel"
output-channel="requestChannel">
<int:header name="Api-Key" value="pass"/>
</int:header-enricher>
You should declare DefaultHttpHeaderMapper.outboundMapper() bean with the setUserDefinedHeaderPrefix(null) and including that your custom Api-Key header mapping. After that you should replace mapped-request-headers attribute with the header-mapper reference.
We have revised the feature and decided to remove "X-" default prefix in the next version.
For more info please, see here Custom HTTP headers : naming conventions and here https://jira.spring.io/browse/INT-3903.
Thanks to #Artem for clarifying, and Gary's post here Spring Integration Http Outbound Gateway Header Mapper
I was able to solve the issue
<int:channel id="requestChannel"/>
<int:gateway id="requestGateway"
service-interface="org.springframework.integration.samples.http.RequestGateway"
default-request-channel="requestChannel">
<int:default-header name="Api-Key" value="pass" />
</int:gateway>
<int-http:outbound-gateway request-channel="requestChannel"
header-mapper="headerMapper"
url="http://localhost:9090/balance"
http-method="GET"
expected-response-type="java.lang.String"/>
<beans:bean id="headerBean"
class="org.springframework.integration.samples.http.HeaderBean" />
<bean id="headerMapper"
class="org.springframework.integration.http.support.DefaultHttpHeaderMapper">
<property name="inboundHeaderNames" value="*" />
<property name="outboundHeaderNames" value="HTTP_REQUEST_HEADERS, Api-Key" />
<property name="userDefinedHeaderPrefix" value="" />
</bean>

HTTP-Outbound gateway not showing special characters -encoding breaks

We have a client which uses http-outboundgateway to place REST calls
<int-http:outbound-gateway request-channel="glNewsRequestChannel"
url="${gl.url}" http-method="GET" expected-response-type="java.lang.String"
reply-channel="glHeaderEnricher" charset="iso-8859-1">
<int-http:uri-variable name="site_code"
expression="payload" />
</int-http:outbound-gateway>
When response is fetched and saved logged in a file, it shows some jumbled character -which is basically unable to translate in specific encoding.
I referred SI documentation which mention unless a factory is specified Java URLconnection class is used to place REST call.
To narrow down the issue, I wrote a small Java program and used the URLconnection class directly without using any out of box template or gateway -it successfully fetches and renders all the special character. I tried another standalone app which apache http library and it was also able to fetch the character.
Any configuration which I am missing as part of SI ?
Further investigation revealed that we were using wrong message converter -Instead of using String converter if we use byte[], in accordance to bytearraymessageconverter -it works as expected.
<int-http:outbound-gateway request-channel="glNewsRequestChannel" url="${gl.url}"
http-method="GET" message-converters="byteArrayHttpMessageConverter"
expected-response-type="byte[]" reply-channel="glHeaderEnricher"
charset="iso-8859-1"> <int-http:uri-variable name="site_code"
expression="payload" />
</int-http:outbound-gateway>
Where byteArrayHttpMessageConverter can be defined as :
<bean id="byteArrayHttpMessageConverter"
class="org.springframework.http.converter.ByteArrayHttpMessageConverter">
</bean>

Resources