I have a gateway URL: https://baseurl/1.0.0/Api/Users/Login
and require to rewrite in lower case using URLRewrite Mediator.
Require to navigate here: https://baseurl/1.0.0/api/users/login
What should I set in value, type and fragment attributes.
<rewrite>
<rewriterule>
<action value="tolowercase{url}" type="set" fragment="path"/>
</rewriterule>
</rewrite>
Instead of URL rewrite mediator, you can easily get this done with property mediator.
<sequence xmlns="http://ws.apache.org/ns/synapse" name="NewAPI:v1.0.0--In">
<property name="URL_POSTFIX" expression="get-property('axis2','REST_URL_POSTFIX')" />
<property name="URL_POSTFIX_LOWER_CASE" expression="lower-case(get-property('URL_POSTFIX'))"/>
<property name="REST_URL_POSTFIX" expression="get-property('URL_POSTFIX_LOWER_CASE')" scope="axis2" />
</sequence>
Related
I have following JSON data:
{
"CustomerNames":{
"Update":[
{
"CustName":"Name1",
"id":"3"
},
{
"CustName":"Name3",
"id":"32"
}
],
"Create":[
{
"Name":"Name2"
}
]
}
}
If the Update JSONARray exists I need to call UpdateCustomer Sequence. And if the Create JSONArray exists I need to call CreateCustomer Sequence. I am trying to achieve this using Conditional Router Mediator. I have tried the below code for conditional routing:
<property expression="json-eval($.CustomerNames.Update)" name="CREATE_PAYLOAD" scope="default" type="STRING"/>
<property expression="json-eval($.CustomerNames.Create)" name="UPDATE_PAYLOAD" scope="default" type="STRING"/>
<conditionalRouter continueAfter="true">
<conditionalRoute asynchronous="true" breakRoute="false">
<condition>
<match regex="true" source="boolean(get-property('CREATE_PAYLOAD'))"/>
</condition>
<target sequence="CREATE_CUSTOMER"/>
</conditionalRoute>
<conditionalRoute asynchronous="true" breakRoute="false">
<condition>
<match regex="true" source="boolean(get-property('UPDATE_PAYLOAD'))"/>
</condition>
<target sequence="UPDATE_CUSTOMER"/>
</conditionalRoute>
</conditionalRouter>
But this is not giving desired output. Am I doing anything wrong here?
The Conditional Router Mediator was removed from EI 6.5.0 onwards and the latest version doesn't support it. Therefore you may need to use the Switch Mediator to call the required sequences. In the Switch Mediator, if a matching case is found, it will be executed, and the remaining switch cases are not processed. Since you need to call both sequences, you can use two switch mediators as follows,
<property expression="json-eval($.CustomerNames.Update)" name="CREATE_PAYLOAD" scope="default" type="STRING"/>
<property expression="json-eval($.CustomerNames.Create)" name="UPDATE_PAYLOAD" scope="default" type="STRING"/>
<switch source="boolean(get-property('CREATE_PAYLOAD'))">
<case regex="true">
<sequence key="CREATE_CUSTOMER"/>
</case>
<default/>
</switch>
<switch source="boolean(get-property('UPDATE_PAYLOAD'))">
<case regex="true">
<sequence key="UPDATE_CUSTOMER"/>
</case>
<default/>
</switch>
For more information check https://ei.docs.wso2.com/en/latest/micro-integrator/references/mediators/switch-Mediator/
I have made Filter mediator to check email subject has specific keyword or not using REGEX.
<property value="Test SR AWS onboarding of AWS server" name="emailSubject" scope="default" type="STRING" />
<filter regex=".*SRAWS.*|.*SR AWS.*|.*SRSAP.*|.*SR SAP.*|.*SRFW.*|.*SR FW.*|.*SRSEC.*|.*SR SEC.*|.*INAWS.*|.*INSAP.*|.*INFW.*|.*INSEC.*"
source="get-property('emailSubject')">
<then>
<log level="custom">
<property name="==Test Case ===" value="pass" />
</log>
</then>
<else>
<log level="custom">
<property name="==Test Case ===" value="Fail" />
</log>
</else>
</filter>
Plenty of keywords(more than 60) are required in my case. I have hard coded keyword in Code, Instead of this, i am trying to store these keyword in somewhere(eg. localentry) and try to match subject with this to make code as generic.
Localentry:
<?xml version="1.0" encoding="UTF-8"?>
<localEntry key="EmailTicketing_Keyword" xmlns="http://ws.apache.org/ns/synapse">
<SR>.*SRAWS.*|.*SR AWS.*|.*SRSAP.*|.*SR SAP.*|.*SRFW.*|.*SR FW.*|.*SRSEC.*|.*SR SEC.*</SR>
</localEntry>
Reading from Localentry:
<property expression="get-property('EmailTicketing_Keyword')" name="tokenconfig" scope="default" type="OM"/>
<property expression="$ctx:tokenconfig//*[local-name()='SR']" name="SR" scope="default" type="STRING"/>
I am unable to use above property( SR) to match with subject in Filter Mediator.
Is there any way to achieve my use case?
PS: new Keyword may be added in future, to avoid code level changes whenever key word change required i just add new keyword in localentry instead of code which will work fine since keyword change is generic,That's why i am trying this.
Your localEntry as XML wont work, because it starts as . (dot) and wstx parser will throw error. Use instead LocalEntry as Text:
<localEntry xmlns="http://ws.apache.org/ns/synapse" key="RegTicketing">
.*SRAWS.*|.*SR AWS.*|.*SRSAP.*|.*SR SAP.*|.*SRFW.*|.*SR FW.*|.*SRSEC.*|.*SR
SEC.*
</localEntry>
For using that as regexp You need use ScriptMediator as below:
<property name="tokenconfig" expression="get-property('RegTicketing')" scope="default" type="STRING"/>
<script language="js">
var regStr = mc.getProperty('tokenconfig').toString();
var testStr = mc.getProperty('emailSubject').toString();
var regExp = new RegExp(regStr);
mc.setProperty('testResult',regExp.test(testStr).toString());
</script>
And you can use that testResult in FilterMediator:
<filter xpath="$ctx:testResult='true'">
As per the documentation [1] of the filter mediator, the regex only accepts a string. Therefore according to this you will not be able to dynamically set the value of the regex expression in the filter mediator.
As an alternative approach you can use a class mediator for this. You can feed the content of the local entry and the email subject, then evaluate the regex expression within the class mediator.
[1]-https://docs.wso2.com/display/EI660/Filter+Mediator+
Solution:
<script language="js"><![CDATA[var log = mc.getServiceLog();
log.info("===Inside keyword Match Script Mediator===" );
var emailSubject = mc.getProperty('transemailSubject').toString();
log.info("EmailSub::" + emailSubject);
var keywordSR = mc.getProperty('SR').toString();
//log.info("SR Keywords::" + keywordSR);
var regExpSR = new RegExp(keywordSR);
mc.setProperty('SR_Match',regExpSR.test(emailSubject).toString());
log.info("SR_Match::" + mc.getProperty('SR_Match'));]]></script>
<filter xpath="$ctx:SR_Match='true'">
<then>
<log level="custom">
<property name="==Test Case ===" value="pass" />
</log>
</then>
<else>
<log level="custom">
<property name="==Test Case ===" value="Fail" />
</log>
</else>
</filter>
I've got an API that uses dynamic endpoints. Now I want it to also do load balancing. I know how to do that using element, however when using dynamic endpoints in APIM you only manipulate the "To" header.
Below is the mediation sequence used to set the endpoint. Instead of addressing just a single endpoint in each case, I'd like to be able to loadbalance between 2 servers.
Any thoughts?
Thanks.
<?xml version="1.0" encoding="UTF-8"?>
<sequence name="inSequence_clientEquipmentsAPI_1_2_STG" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
<!-- check for healthcheck operation -->
<filter xpath="get-property('To')='/etc/equipments/client/1.0/healthCheck'">
<!-- if healthCheck, directs to healthCheck API (EI)-->
<then>
<property name="REST_URL_POSTFIX" scope="axis2" action="remove"/>
<header name="To" value="http://10.220.160.36:8290/healthCheck/clientEquipments"/>
</then>
<!-- else direct to regular clientEquipment API (EI)-->
<else>
<property name="newContext" expression="substring-after(get-property('To'),'/etc')"/>
<header name="To" expression="fn:concat('http://10.220.160.36:8290', $ctx:newContext)"/>
</else>
</filter>
</sequence>
I need to append a fixed Authorization header to an API endpoint. This is an application specific token for my endpoint system so I do not need API subscribers to enter this information nor want them in the know.
An almost similar question was raised before but hasn't been answered.
The documentation here doesn't provide specific details and is a bit obscure so I am lost on how to achieve this. Has anybody done this?
Appreciate any help, cheers!
Do you want to set this as a custom HTTP header and send it to the backend? If yes, then you can use a property mediator to set this as a transport scope property just before the send mediator inside inSequence of your API, as shown below. Have a look at the property Fixed-Authorization set just before the send mediator.
<?xml version="1.0" encoding="UTF-8"?>
<api xmlns="http://ws.apache.org/ns/synapse"
name="admin--Hello"
context="/hello"
version="1.0.0"
version-type="url">
<resource methods="POST GET OPTIONS DELETE PUT"
url-mapping="/*"
faultSequence="fault">
<inSequence>
<filter source="$ctx:AM_KEY_TYPE" regex="PRODUCTION">
<then>
<property name="Fixed-Authorization" value="yourAppToken" scope="transport"/>
<send>
<endpoint name="admin--Hello_APIproductionEndpoint_0">
<http uri-template="http://echo.jsontest.com/key/value/one/two"/>
</endpoint>
</send>
</then>
<else>
<sequence key="_sandbox_key_error_"/>
</else>
</filter>
</inSequence>
<outSequence>
<send/>
</outSequence>
</resource>
<handlers>
<handler class="org.wso2.carbon.apimgt.gateway.handlers.security.APIAuthenticationHandler"/>
<handler class="org.wso2.carbon.apimgt.gateway.handlers.throttling.APIThrottleHandler">
<property name="id" value="A"/>
<property name="policyKey" value="gov:/apimgt/applicationdata/tiers.xml"/>
</handler>
<handler class="org.wso2.carbon.apimgt.usage.publisher.APIMgtUsageHandler"/>
<handler class="org.wso2.carbon.apimgt.usage.publisher.APIMgtGoogleAnalyticsTrackingHandler">
<property name="configKey" value="gov:/apimgt/statistics/ga-config.xml"/>
</handler>
<handler class="org.wso2.carbon.apimgt.gateway.handlers.ext.APIManagerExtensionHandler"/>
</handlers>
</api>
If you access the API, this property will be sent as a HTTP header to your backend endpoint. You can refer this post for more detailed explanation.
If you just want to pass this application token to the backend (but not as HTTP header), then you can pass it to the backend using JWT. Refer this document for more details.
I am trying to implement ESB solution to replace a web-tier part of a complex web-service architecture. The web-tier just receives the request from clients and distributes to a given set of app-tier instances.
Since the end-points are already defined and used by clients, I had to build the ESB proxy using the "CustomURI" approach as described here - http://achala11.blogspot.com/2012/08/access-wsdl-for-customuri-wso2-esb.html - to expose the end-point and wsdl.
Note that ServiceURI only allows to specify a fixed context path (correct me if I am wrong). For example:
If WSDL end-point is http:// localhost:8280/CustomURL/Part1/Part2?wsdl, the corresponding ServiceURI entry is
<parameter name="ServiceURI">/CustomURL/Part1/Part2</parameter>
What I want to use is an expression like this:
<parameter name="ServiceURI">/CustomURL/*</parameter>
to indicate that all requests that starts with /CustomURL in the context path will be handled by the proxy. Inside the proxy, I like to propagate the context URI to the endpoint defined in the send block. I think I found a RESTful way (didn't get it to work completely) of doing what I am trying to do here. As you can see, I can specify a context in the api and then use url-mapping option of resource to route all request to the api block. Later I am trying to use the "http endpoint" approach to construct the endpoint with the contextURI appended.
<api xmlns="http://ws.apache.org/ns/synapse" name="customService1" context="/CustomServices">
<resource methods="POST" url-mapping="/*">
<inSequence>
<log level="custom">
<property name="uri.var.servicepath" expression="get-property('To')"/>
</log>
<send>
<endpoint name="HTTPEndpoint">
<http method="POST" uri-template="http://localhost:8001/{uri.var.servicepath}"/>
</endpoint>
</send>
</inSequence>
<outSequence>
<send/>
</outSequence>
</resource>
</api>
I hope you can help me with a similar solution for SOAP services - a way to specify a contextURI and then include the contextURI to the final endpoint that the proxy will send the request to. Note that the endpoints will be a list of entries (load balanced entries), but to keep things simple, I just kept one endpoint entry above.
I am new to WSO2 esb and so correct me if you find any mistakes.
Use case:
Check this out - http://achala11.blogspot.com/2012/08/access-wsdl-for-customuri-wso2-esb.html . It shows a way to allow custom wsdl URL for SOAP services in WSO2. Well, in my case, the services are already in place and are consumed by clients. So I couldn't use the "generated" wsdl endpoint from WSO2 and had to make sure that the existing wsdl and service URLs are going to work through WSO2. Note that I am dealing with SOAP here and there are plenty of examples for RESTful services(including REST_URL_POSTFIX to handle endpoint manipulation).
The key information you need is that there are two sequences in WSO2 that all requests go through - namely "main" and "fault" (fault is used only when there is a failure scenario).
As explained in my original question, getting the proxy service to do what I want became very challenging. Proxy service doesn't offer much in terms of propagating context to the endpoint or specifying expressions for ServiceURI variable. Then I looked at the "main" sequence entry as explained in the link I posted above. What WSO2 team is doing is just using regular expression to detect the incoming context and if it has "wsdl", they are routing the requests to a fixed wsdl endpoint and stopping the flow further. Well, I figured that we don't have to keep that code in the main sequence itself. Sequences can be chained. What that means is that you can call another sequence from main where you can do lot of magic (I didn't want to add lot of logic into the main sequence itself - my c/c++/java experiences might be stopping me from that :)) - If you are familiar with programming, sequences are like method/function calls. Main is the entry point and then you call whatever method you want inside and make further chained sequences from it etc).
First is the main sequence (filter is not needed - basically, .
<sequence name="main">
<in>
<log level="full"/>
<sequence key="ISP_seq"/>
</in>
<out>
<send/>
</out>
<description>The main sequence for the message mediation</description>
</sequence>
Now the ISP_seq where the routing of requests based on context (note the regular expressions used).
<sequence xmlns="http://ws.apache.org/ns/synapse" name="ISP_seq">
<in>
<log level="custom">
<property xmlns:ns="http://org.apache.synapse/xsd" name="Current URL" expression="get-property('To')"/>
</log>
<conditionalRouter continueAfter="false">
<conditionalRoute breakRoute="false" asynchronous="false">
<condition>
<or>
<match type="url" regex="/firstService/10\.06/.*"/>
<match type="url" regex="/firstServiceVariant/.*"/>
</or>
</condition>
<target sequence="firstService_seq"/>
</conditionalRoute>
<conditionalRoute breakRoute="false" asynchronous="false">
<condition>
<match type="url" regex="/secondService.*"/>
</condition>
<target sequence="second_seq"/>
</conditionalRoute>
</conditionalRouter>
</in>
</sequence>
Now inside the firstService_seq, you will receive all requests that has a context URI - /firstService/10.06/ (followed by anything - including ?wsdl :)) or /firstServiceVariant/ (followed by anything).
<match type="url" regex="/firstService/10\.06/.*"/>
<match type="url" regex="/firstServiceVariant/.*"/>
Ok - now to the Sequence that is going to handle the firstService and the other service.
<sequence xmlns="http://ws.apache.org/ns/synapse" name="firstService_seq">
<in>
<!-- FIRST let us handle the WSDL requests. -->
<property name="REST_URL_POSTFIX" action="remove" scope="axis2"/>
<switch xmlns:ns="http://org.apache.synapse/xsd" source="get-property('To')">
<case regex="/firstService/10\.06/service\?[Ww][Ss][Dd][Ll]">
<send>
<endpoint>
<address uri="http://myappServer:10011/firstService10.06?wsdl" format="get"/>
</endpoint>
</send>
</case>
</switch>
<send>
<!-- below here, we will handle the actual SOAP requests -->
<endpoint>
<loadbalance algorithm="org.apache.synapse.endpoints.algorithms.RoundRobin">
<endpoint name="firstFarm_7011">
<address uri="http://hostA:7011/firstService/10.06/service"/>
</endpoint>
<endpoint name="firstFarm_7021">
<address uri="http://hostA:7021/firstService/10.06/service"/>
</endpoint>
<endpoint name="secondFarm_7011">
<address uri="http://hostX:7011/firstService/10.06/service"/>
</endpoint>
</loadbalance>
</endpoint>
</send>
</in>
<out>
<send/>
</out>
</sequence>
I am sorry for the long explanation. Somehow, I was not able to figure this out from the existing documentation. I wish the same features are available through Proxy Service as well as that is what you will think of (at least I was) when you are considering to use a ESB for the use case in my question.
Hope it helps someone. As I said earlier, correct me if I made any mistakes or if there is a better approach.
I found a cleaner/better solution - it is just an enhanced version of the above answer.
The main challenge is to get the SOAP WSDL and the Service endpoint (Context URI) work without forcing it like it happens on a proxy service approach. Note that if you can work with the contextURI WSO2 team suggests (/services//), you don't have to do any of these. The standard documentation will have all the details you need.
The logic is:
Define 3 sequences (I split them into three, but you can put all these in just one sequence as well).
main sequence (the standard built-in one - this is the sequence that gets all traffic if a request doesn't follow proxy service rules already defined in ESB). In main sequence, we just route all the incoming requests to another sequence where we do the filtering/conditinal routing.
<sequence name="main">
<in>
<log level="full"/>
<sequence key="routing_seq"/>
</in>
<out>
<send/>
</out>
<description>The main sequence for the message mediation</description>
</sequence>
*routing_sequence*
Just like in the first answer, we are going to route the incoming requests to other special sequences based on the context URI in the request.
<sequence xmlns="http://ws.apache.org/ns/synapse" name="routing_seq">
<in>
<log level="custom">
<property xmlns:ns="http://org.apache.synapse/xsd" name="Current URL" expression="get-property('To')"/>
</log>
<conditionalRouter continueAfter="false">
<conditionalRoute breakRoute="false" asynchronous="false">
<condition>
<or>
<match type="url" regex="/firstService/10\.06/.*"/>
<match type="url" regex="/firstServiceVariant/.*"/>
</or>
</condition>
<target sequence="firstService_seq"/>
</conditionalRoute>
<conditionalRoute breakRoute="false" asynchronous="false">
<condition>
<match type="url" regex="/secondService.*"/>
</condition>
<target sequence="second_seq"/>
</conditionalRoute>
</conditionalRouter>
</in>
</sequence>
*firstservice_seq*
Now we are ready to handle the incoming request - note that we identified the application as "firstservice" in the previous step. There are two kinds of requests you can receive here - one is for WSDL and the other one is a soap request
<sequence xmlns="http://ws.apache.org/ns/synapse" name="firstService_seq">
<in>
<property name="REST_URL_POSTFIX" scope="axis2" action="remove"/>
<!-- We are checking whether the request ends with a ?wsdl or .xsd -->
<!-- For that we are using the context URI present in the 'To' field -->
<!-- if it is a wsdl or xsd request, we are converting it to a HTTP GET method -->
<!-- and sending to the final endpoint. All soap operation requests are sent as HTTP POST -->
<switch xmlns:ns="http://org.apache.synapse/xsd" source="get-property('To')">
<case regex=".*(?:\?[Ww][Ss][Dd][Ll]|\.[Xx][Ss][Dd])\s*$">
<property name="HTTP_METHOD" value="GET"/>
<property name="messageType" value="text/xml"/>
<send receive="wsdl_transformer_seq">
<endpoint key="local-enrty-firstservice-ep-key"/>
</send>
<drop/>
</case>
<!-- default means non-wsdl/non-xsd - which means a regular soap operation on the service -->
<default>
<property name="HTTP_METHOD" value="POST"/>
<send>
<endpoint key="local-enrty-firstservice-ep-key"/>
</send>
</default>
</switch>
</in>
<out>
<send/>
</out>
</sequence>
Hope you read the comments in the sequence definition. As you can see, I am converting the wsdl and xsd requests into HTTP GET to avoid any confusion at the app-tier as otherwise, there could be some junk SOAP body parts get injected from somewhere in the flow).
So basically, we check the 'To' property which contains a Context URI like /firstservice/10.06/service?WSDL (if it was a WSDL request) or /firstservice/10.06/service - if it was a SOAP request. Based on the value, we decide what to do with the request.
Note the below section in the wsdl logic:
<send receive="wsdl_transformer_seq">
<endpoint key="local-enrty-firstservice-ep-key"/>
</send>
<drop/>
</send>
What happens is that when we pull the wsdl from the endpoint (which I will explain shortly), schemaLocation and soap:address fields contain the information (hostname and port) of actual server instance that processed the request. This is an unwanted result as you are exposing your internal details to the clients and others. So we should mask it. The way to do that is to use a special feature in WSO2. In a send, you can specify another sequence that will receive the results of the send before it goes to the client. It is more or less like you define an <out> portion in a sequence. Since we don't want this particular manipulation happen to all requests, we are not defining a special sequence that gets applied to only wsdl/xsd reqeusts. In the wsdl_transformer_seq, we use XSLT to change the hostname and port present in the wsdl or xsd response.
wsdl_transformer_seq
<sequence name="wsdl_transformer_seq">
<xslt xmlns:ns="http://org.apache.synapse/xsd"
key="xslt-url-manipulator"
source="/"/>
<send/>
</sequence>
Note that I externalized these entries (xslt transformer for example) and get them loaded through a local-entry registry.
<localEntry key="xslt-url-manipulator"
src="file:repository/myapp/resources/transform/url-in-wsdl-transform.xslt"/>
Now the contents of url-in-wsdl-transform.xslt
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
version="2.0">
<xsl:output method="xml" encoding="UTF-8" indent="yes" omit-xml-declaration="yes"/>
<xsl:param name="newURL">https://services.mycompany.com</xsl:param>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="soap:address/#location">
<xsl:attribute name="location">
<xsl:value-of select="replace(.,'https?://[^/]*',$newURL)"/>
</xsl:attribute>
</xsl:template>
<xsl:template match="xs:import/#schemaLocation">
<xsl:attribute name="schemaLocation">
<xsl:value-of select="replace(.,'https?://[^/]*',$newURL)"/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
Note the name - https://services.mycompany.com - in the xslt above. You can change it to whatever you want and the schemaLocation and soap:address fields in the wsdl and xsd will now use that in the host:port area
And finally the endpoint local-enrty-firstservice-ep-key
Note that this as well is an externally loaded file - just like the xslt entry above. So I will only post the content of the actul external file.
This was a tough cookie and I had to dig through WSO2 source code and figure out some "undocumented" features. Well, it is "undocumented" in WSO2 world, but documented otherwise as WSO2 uses a third-party library which has many features that are not published in WSO2.
Note that the endpoint points to the app-tier instances and we use the roundrobin algorithm to distribute the traffic to the avilalble app-tier instances.
<endpoint xmlns="http://ws.apache.org/ns/synapse">
<loadbalance algorithm="org.apache.synapse.endpoints.algorithms.RoundRobin">
<endpoint name="firsthost_5012">
<http uri-template="http://firsthost.com:5012{+uri.var.servicepath}"/>
</endpoint>
<endpoint name="firsthost_5022">
<http uri-template="http://firsthost.com:5022{+uri.var.servicepath}"/>
</endpoint>
</loadbalance>
<property xmlns:ns="http://org.apache.synapse/xsd"
name="uri.var.servicepath"
expression="get-property('To')"/>
</endpoint>
There is lot of magic happens here -
First we save the context uri to a special variable called uri.var.servicepath
Now we will use that with the new "http endpoint" feature available from WSO 4.7.0 onwards.
http endpoint uses uri-template - where you can dynamically construct the endpoint. So I don't have to specify the context URI in the configuration -
So let us say the original request we got into ESB was like this:
http://esbhost.com:8280/firstservice/10.06/service
The context uri here is "/firstservice/10.06/service" - so we want this to be appended to the actual app-tier server url. In other words, I want it to become http://firsthost.com:5022/firstservice/10.06/service
In http endpoint, it allows us to use the special variable - uri.var.servicepath that we defined earlier.
<http uri-template="http://firsthost.com:5022{+uri.var.servicepath}"/>
since uri.var.servicepath already contains a '/' at the beginning, I am not specifying separately. But note the + sign in the brackets. What is that for? hmmm - well, it turned out that WSO2 uses the interesting third-party library - "damn good uri processor" - it is mainly used for RESTful APIs. Unfortunately, if you plainly use the field like this, http://firsthost.com:5022{uri.var.servicepath}, the 3rd party library will convert the special characters present in the context uri to their http safe equivalent - something like %20f or whatever. So our url now becomes http ://firsthost:5022%20ffirstservice%20f10.06.... - it is not good. Well here comes the special feature in the 3rd party library that saves the day. If you put a + at the beginning of the special variable, this translation is turned off ;) - voila - we got what we wanted.
So that is it folks. I will try to post the full configuration below (minus the externalized entries that you can find in the above sections)
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://ws.apache.org/ns/synapse">
<registry provider="org.wso2.carbon.mediation.registry.WSO2Registry">
<parameter name="cachableDuration">15000</parameter>
</registry>
<localEntry key="xslt-url-manipulator"
src="file:repository/myapp/resources/transform/url-in-wsdl-transform.xslt"/>
<localEntry key="local-enrty-firstservice-ep-key"
src="file:repository/myapp/resources/endpoint/firstservice-endpoints.xml">
</localEntry>
<sequence xmlns="http://ws.apache.org/ns/synapse" name="routing_seq">
<in>
<log level="custom">
<property xmlns:ns="http://org.apache.synapse/xsd" name="context URI" expression="get-property('To')"/>
</log>
<conditionalRouter continueAfter="false">
<conditionalRoute breakRoute="false" asynchronous="false">
<condition>
<or>
<match type="url" regex="/firstService/10\.06/.*"/>
<match type="url" regex="/firstServiceVariant/.*"/>
</or>
</condition>
<target sequence="firstService_seq"/>
</conditionalRoute>
<conditionalRoute breakRoute="false" asynchronous="false">
<condition>
<match type="url" regex="/secondService.*"/>
</condition>
<target sequence="second_seq"/>
</conditionalRoute>
</conditionalRouter>
</in>
</sequence>
<sequence name="wsdl_transformer_seq">
<xslt xmlns:ns="http://org.apache.synapse/xsd"
key="xslt-url-manipulator"
source="/"/>
<send/>
</sequence>
<sequence name="fault">
<log level="full">
<property name="MESSAGE" value="Executing default 'fault' sequence"/>
<property name="ERROR_CODE" expression="get-property('ERROR_CODE')"/>
<property name="ERROR_MESSAGE" expression="get-property('ERROR_MESSAGE')"/>
</log>
<drop/>
</sequence>
<sequence name="firstservice_seq">
<in>
<property name="REST_URL_POSTFIX" scope="axis2" action="remove"/>
<switch xmlns:ns="http://org.apache.synapse/xsd" source="get-property('To')">
<case regex=".*(?:\?[Ww][Ss][Dd][Ll]|\.[Xx][Ss][Dd])\s*$">
<property name="HTTP_METHOD" value="GET"/>
<property name="messageType" value="text/xml"/>
<send receive="wsdl_transformer_seq">
<endpoint key="local-enrty-firstservice-ep-key"/>
</send>
<drop/>
</case>
<default>
<property name="HTTP_METHOD" value="POST"/>
<send>
<endpoint key="local-enrty-firstservice-ep-key"/>
</send>
</default>
</switch>
</in>
</sequence>
<sequence name="main">
<in>
<filter xmlns:ns="http://org.apache.synapse/xsd"
source="get-property('To')"
regex="http://localhost:9000.*">
<then>
<send/>
</then>
<else/>
</filter>
<sequence key="routing_seq"/>
</in>
<out>
<send/>
</out>
<description>The main sequence for the message mediation</description>
</sequence>
</definitions>
I know it is a very lengthy post - but wanted to explain the details for those who care.
Hope it helps someone.