HTTP-Outbound gateway not showing special characters -encoding breaks - spring

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>

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

Passing a dynamic input in proxy url wso2 esb

I am trying to simply host a REST service as a proxy service in WSO2 ESB. I am using Custom Proxy to do this. When I run the created proxy, I am not able to pass parameters to the proxy service at run time. How do I do this?
My REST service will be hit on a URL of format:http://ip:host/requestMapping/{name}
The parameter 'name' has to be passed from the UI through the ESB to the service through a proxy service hosted on the ESB. Can you help me with the steps to follow to make this work?
I tried using this page: http://wso2.com/library/articles/2013/12/restful-integration-with-wso2-esb/
But that is for creating APIs which I have been successfully in creating. But I am unable to do this using Proxy services.
Basically in my program, when the user interacts with the UI, he enters a name as input. This name has to be passed to the proxy service hosted in the ESB which should forward this as a path variable to my REST service.
Right now, my service body is:
<inSequence>
<send>
<endpoint>
<http method="POST" uri-template="http://ip:port/resourceMapping/{uri.var.name}"></http>
</endpoint>
</send>
</inSequence>
<outSequence>
<send></send>
</outSequence>
use the + to control encoding as this is part of the URI Template specification. try below code.
<inSequence>
<parameter name="uri.var.name" expression="YOUR EXPRESSION" />
<send>
<endpoint>
<http method="POST" uri-template="http://ip:port/resourceMapping/{+uri.var.name}"></http>
</endpoint>
</send>
</inSequence>
<outSequence>
<send></send>
</outSequence>
WSO2ESB HTTP Endpoint throws exception when using uri.var parameters in the uri-template
You can use the Header mediator to change the value of "To" header to the desired concat expression.
For example, check this link:
Defining dynamic endpoint in wso2esb
Alternatively, if you haven't yet, you can also check the answers to a similar question here: wso2-esb-dynamically-change-endpoint-address
According to this, you should set the property "uri.var.name" in advance. i.e.,
<inSequence>
<parameter name="uri.var.name" expression="" />
<send>
<endpoint>
<http method="POST" uri-template="http://ip:port/resourceMapping/{uri.var.name}"></http>
</endpoint>
</send>
</inSequence>
<outSequence>
<send></send>
</outSequence>
The expression would depend on the way the input is formatted - XML, JSON, etc. You can read more about XPath here: https://docs.wso2.com/display/ESB490/Synapse+XPath+Variables and here: http://www.w3schools.com/xsl/xpath_syntax.asp

Setting http headers processor:http-client

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"/>

How can i validate SPML SOAP Requests in Spring Web Services if their XSDs have Unique Particle Attribution Errors?

I was wondering if anyone could point me in the right direction here.
I'm working on a project that needs to create web service functionality to adhere to the SPML v2 Spec (https://www.oasis-open.org/committees/tc_home.php?wg_abbrev=provision). It's an XML based spec for provisioning services.
I've created the end points that map to the namespace and localpart of the soap requests fine. My issue lies in attempting to validate the payload requests in spring web services using the provided XSDs from the spec itself. From my research, it is an "Open Content Model", and any validation or attempt to compile the XSDs results in Unique Particle Attribution errors.
This happens because the CORE XSD has an "ExtensibleType" complexType that when other complexTypes extend from it causes the error. From my research, i can see why the error is occurring, but i don't want to modify the xsds provided by the spec itself.
Example:
<complexType name="ExtensibleType">
<sequence>
<any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="lax"/>
</sequence>
<anyAttribute namespace="##other" processContents="lax"/>
</complexType>
<complexType name="SearchQueryType">
<complexContent>
<extension base="spml:ExtensibleType">
<sequence>
<annotation>
<documentation>Open content is one or more instances of QueryClauseType (including SelectionType) or LogicalOperator.</documentation>
</annotation>
<element name="basePsoID" type="spml:PSOIdentifierType" minOccurs="0" />
</sequence>
<attribute name="targetID" type="string" use="optional"/>
<attribute name="scope" type="spmlsearch:ScopeType" use="optional"/>
</extension>
</complexContent>
</complexType>
This would result in the following error when attempting to validate the xsds:
cos-nonambig: WC[##other:"urn:oasis:names:tc:SPML:2:0"] and "urn:oasis:names:tc:SPML:
2:0:search":basePsoID (or elements from their substitution group) violate "Unique Particle
Attribution". During validation against this schema, ambiguity would be created for those two
particles.
Since the XSDs are invalid themselves, i'm having a duzy of a time figuring out how i can actually validate payload requests against the XSDS provided by the spec itself.
Adding the PayloadValidatingInterceptor in the spring context file results in the same error when the server attempts to start:
<bean id="validatingInterceptor"
class="org.springframework.ws.soap.server.endpoint.interceptor.PayloadValidatingInterceptor">
<property name="schemas">
<list>
<value>/WEB-INF/xsd/spml/pstc_spmlv2_core.xsd</value>
<value>/WEB-INF/xsd/spml/pstc_spmlv2_search.xsd</value>
</list>
</property>
<property name="validateRequest" value="true"/>
<property name="validateResponse" value="false"/>
</bean>
Thanks for anyone's input ahead of time, not sure if anyone ever ran into this type of issue or not.
Damian
What you need to do is disable the Unique Particle Attribution check. In general, this works in Java (see this SO post), you just need to find a way to configure it... Worst case might be to build your own validator based on the above link - it should work since Spring's XSD schemas are using Apache's implementation.

Resources