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
Related
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.
I'm currently developing a REST Application with Apache Camel (using camel-spring), and getting some confusing behaviour. I have a set of endpoints defined in REST DSL, some are simply proxy requests to another server, and some others are passed on to routes I've defined for data aggregation. The DSL looks as follows:
<rest>
<!-- Specific DSL requests -->
<get uri="/v1/aggregate/data" consumes="application/json" produces="application/json">
<to uri="direct:dataEnrichment" />
</get>
<get uri="/v1/customer/{custId}/devices" consumes="application/json" produces="application/json">
<to uri="direct:getCustomerDevices" />
</get>
<get uri="/v1/login/{custId}" consumes="application/json" produces="application/json">
<to uri="direct:getCustomer" />
</get>
<get uri="/v1/status" consumes="application/json" produces="application/json">
<to uri="direct:statusInfo" />
</get>
<!-- Proxy requests -->
<post uri="/v1?matchOnUriPrefix=true&chunked=false">
<to uri="direct:proxyOut" />
</post>
<get uri="/v1?matchOnUriPrefix=true&chunked=false">
<to uri="direct:proxyOut" />
</get>
<put uri="/v1?matchOnUriPrefix=true&chunked=false">
<to uri="direct:proxyOut" />
</put>
<delete uri="/v1?matchOnUriPrefix=true&chunked=false">
<to uri="direct:proxyOut" />
</delete>
</rest>
The idea is that any requests with no exact matching URI get proxied through to another system (which is not Apache Camel). This saves me having to write a definition for every REST API on the other system (there are a lot).
All was working well, until I added the two requests with {custId} in the URI. Those requests work fine, but every time I try a URI that should get proxied through, I get 405 Method Not Allowed.
EDIT:
I should also have mentioned that I'm using Jetty as the REST component. Camel is running stand-alone, using org.apache.camel.spring.Main to start it up. I'm calling it with Postman at this stage, and the 405 response appears to be coming from Jetty/Camel.
The REST configuration looks like this (The security handler is using the Jetty BasicAuthenticator):
<restConfiguration contextPath="/mobilegateway/api" scheme="http"
host="0.0.0.0" bindingMode="off"
enableCORS="true"
component="jetty" port="8079">
<endpointProperty key="handlers" value="securityHandler" />
<endpointProperty key="sessionSupport" value="true" />
<endpointProperty key="httpClient.idleTimeout" value="30000" />
</restConfiguration>
The Proxy requests all send to the direct:proxyOut route, which looks like this:
<route id="proxyOutbound">
<description>A simple outbound route to proxy REST requests.</description>
<from uri="direct:proxyOut" />
<removeHeaders pattern="Authorization" />
<to
uri="http://{{remoteAddress}}/data/json?bridgeEndpoint=true&throwExceptionOnFailure=false" />
</route>
The intention is that everything after the /v1 in the URI is passed over in the proxied request. I've checked using Wireshark, and the request is not getting proxied. If I remove the routes with {custId} in the path, everything works fine.
Am I doing something wrong or is this a bug in camel/camel-spring?
Camel bug, the details of which can be found here:
https://issues.apache.org/jira/browse/CAMEL-11951
Its not clear whom is returning 405, is it the proxied backend you call, or does it not call that backend at all.
However when you proxy HTTP via Camel, then you may need to remove some CamelHttp* headers that can interfere.
So try adding
<removeHeaders pattern="CamelHttp*" />
The similar bug is still in place, I've filed one here:
https://issues.apache.org/jira/browse/CAMEL-15363
I've managed to make a workaround for my case, see my comment in the bugtracker
I am trying to add some custom JMS headers, required by another 3rd party system to the outgoing message.
I have tried adding the following property mediator:
<property xmlns="http://ws.apache.org/ns/synapse" name="HEADER" value="VALUE" scope="transport" type="STRING"/>
The JMS broker (ActiveMQ) is receiving the HEADER:VALUE but treating it as a property, rather than a header
I know there are reserved JMS header keywords, such as JMS_TIME_TO_LIVE, however these aren't well documented.
I suspect I may have to add something to the TRANSPORT_HEADERS map, however the documentation states it is filled from the client request, and again, these show as properties in ActiveMQ rather than headers
The original was working correctly, and adding the values to the User defined properties collection of the JMS message. This is the correct place to add application headers.
<property xmlns="http://ws.apache.org/ns/synapse" name="HEADER" value="VALUE" scope="transport" type="STRING"/>
The issue was a configuration error in the 3rd party tool.
I have proxy that listens to JMS queue on message broker. When I send the message to a queue, I set custom properties to JMS message. But when I log the message received by the proxy, there is no custom JMS properties. How would I get custom JMS properties in proxy?
I use WSO2 ESB 4.6.0 with ActiveMQ 5.8.0.
<proxy xmlns="http://ws.apache.org/ns/synapse" name="MyProxy" transports="https,TTP,http,jms" statistics="disable" trace="disable" startOnLoad="true">
<target>
<inSequence>
<property name="OUT_ONLY" value="true"/>
<property name="FORCE_SC_ACCEPTED" value="true" scope="axis2"/>
<log level="full"/>
</inSequence>
<outSequence>
<drop/>
</outSequence>
<endpoint>
<address uri="jms:/MyQueue?transport.jms.ConnectionFactoryJNDIName=QueueConnectionFactory&java.naming.factory.initial=org.apache.activemq.jndi.ActiveMQInitialContextFactory&java.naming.provider.url=tcp://localhost:61616&transport.jms.DestinationType=queue" format="pox"/>
</endpoint>
</target>
</proxy>
It is necessary to get transport headers in order to access custom JMS properties. I've found 2 ways for that:
1) from XML configuration:
<log level="custom">
<property name="jms property" expression="get-property('transport', 'custom_prop_key_1')"/>
</log>
2) from custom Class Mediator:
public boolean mediate(MessageContext synCtx) {
((Map)((Axis2MessageContext) synCtx).getAxis2MessageContext().getProperty("TRANSPORT_HEADERS")).get("custom_prop_key_1");
...
}
I do not think they are available in the SOAP message directly. They should be available in Axis2 / Transport scope. Usually JMS transport add only the JMS message's payload to SOAP body. So please try following.
Can you check them retrieving using properties in ESB and log them.
<log level="custom">
<property name="JMS_PROPERTY---->" expression="get-property('axis2','your-property-name')"/>
</log>
You can refer this on scope of properties. (If it is set at Transport headers you can change scope from 'axis2' to 'transport' and try.)
I have not personally tried this and suggesting the answer logically.
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>