Creating a blocking transport sender/receiver
All,
I'm looking to create a blocking transport sender/receiver in order to handle request in an apache http server/tomcat set up that is connected via ajp.
I guess my first question is...
Is this possible? If so are there any examples that show this. I've attempted to proxy the requests but when the request is running under SSL to the ESB via the proxy it is extremely slow.
Any help would be greatly appreciated.
Thanks,
J
- Login or register to post comments
- Printer friendly version
- 260 reads











Re:Creating a blocking transport sender/receiver
Hi J
I believe what you want is
Apache < -(AJP) -> ESB (on tomcat as web app) < -(https/http) -> External
One solution is to proxy the request to the ESB. It is what you have done and it was slow when using https.
For other solution (I haven’t try this and just a suggestion), you have to do some code (not much).
You want a blocking sender/receiver but in ESB we used non blocking one. On the other hand, we are not encouraging to use admin console transport. Therefore, you have to do little bit code.
First, I believe you are using ESB as a web application in tomcat container.
In axis2, you can’t specify two http/https pair with same name (In axis2.xml). Therefore, let’s take our transport name as “blockhttp”. Then you have to register it in axis2.xml.
You have to add another HTTP connector to tomcat (port 8085)
<transportReceiver name="blockhttp”
class="org.apache.axis2.transport.http.SimpleHTTPServer">
<parameter name="port">8085</parameter
</transportReceiver>
<transportSender name="blockhttp"
class="org.apache.axis2.transport.http.CommonsHTTPTransportSender">
<parameter name="PROTOCOL">HTTP/1.1</parameter>
<parameter name="Transfer-Encoding">chunked</parameter> </transportSender>
(You can refer to axis2.xml from axis2 distribution)
First you have to write a Servlet that extends AxisServlet. Take a look at SynapseAxisServlet or ESBServlet. You have to override one method as follows. Take SynapseAxisServlet and copy to another file and edit it.
protected MessageContext createMessageContext(HttpServletRequest req, HttpServletResponse resp) throws IOException {
MessageContext msgContext = super.createMessageContext(req, resp);
TransportInDescription adminTransIn = axisConfiguration.getTransportIn("blockhttp");
if (adminTransIn != null) {
msgContext.setTransportIn(adminTransIn);
msgContext.getOptions().setTransportIn(adminTransIn);
}
TransportOutDescription adminTransportOutDescription =
axisConfiguration.getTransportOut("blockhttp");
if (adminTransportOutDescription != null) {
msgContext.setTransportOut(adminTransportOutDescription);
msgContext.getOptions().setTransportOut(adminTransportOutDescription);
}
return msgContext;
}
Then you have to move to the synapse code based
MessageHelper.java
Checks the method
public static org.apache.axis2.context.MessageContext clonePartially(
org.apache.axis2.context.MessageContext ori) throws AxisFault {
…..
}
And add following lines to it (append)
newMC.getOptions().setTransportOut(ori.getTransportOut());
newMC.getOptions().setTransportIn(ori.getTransportIn());
Now take the web.xml of ESB and add servlet and servlet mapping
<servlet>
<servlet-name>BlockServlet</servlet-name>
<servlet-class>org.my.blocking.BlockServlet </servlet-class>
</servlet>
<servlet-mapping>
<servlet-name> BlockServlet </servlet-name>
<url-pattern>/blockhttp/*</url-pattern>
</servlet-mapping>
Now any request with context as >/blockhttp/* should go to the servlet you have written.
Now if you run esb with default configuration and if the sample server is setup and if you invoke esb as
Ant stockquote -Daddurl=http://localhost:9000/soap/SimpleStockQuoteService -Dtrpurl=https://localhost:9444/esb/blockhttp
It should work (now ESb is on https://localhost:9444/esb/blockhttp)
But if you are trying a sample which has an explicitly specified endpoint with URI, then, you have to change some code in the synapse to work this. This is because , axis2 pick transport based on the protocol and name of the transport definition in axis2.xml.Therefore,if the address of the endpoint is http://yyyy/yy/ then , always pick the transport definition with name ‘http’ from axis2.xml.
(take a look at ClientUtils.java from axs2 code base , it show how transport in and out resolved )
To fix , this let’s introduce an attribute to endpoint ‘use’ and if this attribute is present , take the corresponding transport using value of this attribute. You have to add code to process this attribute (DefaultEndpointFactory) …Two or three line code. (If you want it serialize, then you also have to change DefaultEndpointSerializer ).
Then look at Axis2FlexibleMEPClient and after MessageContext axisOutMsgCtx = cloneForSend(originalInMsgCtx); or inside it’s logic.
Take value of the attribute ‘use’ and if it is available get TransportIn and TransportOut using
newMC.getOptions().setTransportOut(axisConfiguration.getTransportOut(“value of ‘use’ attribute”));
newMC.getOptions().setTransportIn(axisConfiguration.getTransportIn(“value of ‘use’ attribute”);
You may now not need the suggested code change in the MessageHelper.java.
The above logic has to carefully be changed.
I believe, If you are enable AJP connector in the tomcat and use its port as ‘blockhttp” port, then, you may can directly connect apache and ESB (tomcat war). But, I don’t know, I haven’t use AJP or even try out.
Really, I am busy; otherwise, I could have able to help you by doing these changes myself and getting it work.
Thanks
Indika
Thank you and I will give it a try
Indika,
Thank you for the explanation above... As you already know I'm not afraid to make changes in the code ;) based on some of the stuff I've already contributed to you all... This one is very tricky and I actually had it working but as you said, when trying to go to another transport it was broken...
When I added:
public static org.apache.axis2.context.MessageContext clonePartially(
org.apache.axis2.context.MessageContext ori) throws AxisFault {
…..
}
And add following lines to it (append)
newMC.getOptions().setTransportOut(ori.getTransportOut());
newMC.getOptions().setTransportIn(ori.getTransportIn());
It messed up all the other communications to the other transports which is not good. lol... But I have already created an override servlet that extends ESBServlet. Let me take a look at some of the alternatives that you have suggested and see what I can figure out... As always if I'm able to get this to work I will contribute it back... If you do have some spare time and want to try and help I'm all for it... lol... Is there another way to communicate or do I always have to post something on the boards.
Thanks again,
J
Working implementation of blocking transport sender/receiver
Indika,
HaHa... So apparently I had all the working part in place needed to do this while maintaining communication to all the other transports. All I had to do is set up the axis2.xml file correctly.
Based on overriding the ESBServlet all I had to do is add:
protected MessageContext createMessageContext(HttpServletRequest req, HttpServletResponse resp) throws IOException {
MessageContext msgContext = super.createMessageContext(req, resp);
TransportInDescription adminTransIn = axisConfiguration.getTransportIn("blockhttp");
if (adminTransIn != null) {
msgContext.setTransportIn(adminTransIn);
msgContext.getOptions().setTransportIn(adminTransIn);
}
TransportOutDescription adminTransportOutDescription =
axisConfiguration.getTransportOut("blockhttp");
if (adminTransportOutDescription != null) {
msgContext.setTransportOut(adminTransportOutDescription);
msgContext.getOptions().setTransportOut(adminTransportOutDescription);
}
return msgContext;
}
Added the necessary logic to handle the what to display when going to esb/soap and also how to handle REST based requests.
Once again thank you for jogging my mind with what you stated above..
Note:
You were correct when saying you don't have to add:
newMC.getOptions().setTransportOut(axisConfiguration.getTransportOut(“value of ‘use’ attribute”));
newMC.getOptions().setTransportIn(axisConfiguration.getTransportIn(“value of ‘use’ attribute”);
All I need to so was configure the axis2.xml to send the blocking request back on http(s).
Thanks again,
J
Nice to here that
Hi J
Have you tried the scenario, that, ESB has an external endpoint with http uri?. Because, if the endpoint URI is http one, then axis2 pick the transport which is registered as ‘http’ in axis2.xml (in this case non-blocking one) unless MessageContext.getOptions().getTransportOut() / getTrasportIn() are present. If you look at the ClientUtils.java from axis2 code [1], you can see it. That is why I thought you may need to introduce an attribute to the Endpoint (‘use’ or ‘useTransport’) and if that is present then get the transport out and in from axis2 configuration using attribute value of (‘use’ or ‘useTransport’ ) and set those.
In that case, I thought that only if the (‘use’ or ‘useTransport’) is present, you may need to add the flowing code.
newMC.getOptions().setTransportOut(axisConfiguration.getTransportOut(“value of ‘use’ attribute”));
newMC.getOptions().setTransportIn(axisConfiguration.getTransportIn(“value of ‘use’ attribute”);
Then
If ESB is listening by blocking transport and if you want to call external service with blocking one, then you have to add use=’blockhttp’ to endpoint.
If ESB is listening by blocking transport and if you want to call external service with some other transport (except non-blocking one), then you must avoid adding use=’blockhttp’. Then, it mimics the current behavior. (Same for when listing on some other transport and send using some other transport – Current behavior)
By the way, if you have got work every scenario (specially transport switching) same as when we use non-blocking one, could you please create a JIRA and submit what you have done? Then, any user who would need same as what you had can use it. And also, if others are like to have this feature with ESB, we can add those to the synapse /ESB code base.
Thanks
Indika
[1] http://www.devdaily.com/java/jwarehouse/axis2-1.3/modules/kernel/src/org/apache/axis2/description/ClientUtils.java.shtml
Re: Nice to here that
Indika,
I now see what you are saying... In my configuration I have replaced both the non-blocking http and https transportSender/transportReceiver with blocking transportSender/transportReceiver. By doing this the ESB runs as it is supposed to. You are able to switch transports and all.... However when trying to go from a blocking to an non-blocking transport this fails. Actually it doesn't fail but the request is delayed by one and messes up how they are handled all together..
I guess my question is:
If you have a situation like mine where you require all http(s) request coming in on blocking transports... why would you need to go from a blocking to a non-blocking? Couldn't that cause a bottle neck eventually?
In the configuration I have I keep all http/s on blocking which is why everything is working.
Thoughts?
Thanks,
J
Re: Nice to here that
Hi J
In many situations, it is sure that either one of blocking or non blocking transport will be required.
But, think a scenario, there is two proxy services. Request to the One is through an apache fond end (AJP) where you may need blocking one.
But for other, due to some reason need a non-blocking one and direct connection from client without Apache frond end.
Then, it needs to available both blocking and non-blocking. I know, this may not come in many case, specialty in a production environment. But, there may be a requirement for some one else.
Thanks
Indika
Re: blocking transports
Makes sense...
I will create a JIRA ticket with what I have currently... Just so you and everybody knows what I've done only extends the ESBServlet in order to handle REST and SOAP based request and to write out the HTML that displays what services are available... Just as if you went to one of the non-blocking transports... I did not have to change any underling functionality within the ESB...
With that said... currently without altering some of the synapse/esb code base.. in order to get this type of functionality you must switch both the http and https non-blocking transports to blocking. I just re-used what was already being used by the ESBServlet...
Transport Receivers:
< transportReceiver name="http" class="org.wso2.esb.transport.tomcat.HttpsTransportListener">
< /transportReceiver>
< transportReceiver name="https" class="org.wso2.esb.transport.tomcat.HttpsTransportListener">
< /transportReceiver>
Transport Senders:
< transportSender name="http" class="org.apache.axis2.transport.http.CommonsHTTPTransportSender">
< parameter name="PROTOCOL">HTTP/1.1
< parameter name="Transfer-Encoding">chunked
< !-- This parameter has been added to overcome problems encounted in SOAP action parameter -->
< parameter name="OmitSOAP12Action">true
< /transportSender>
< transportSender name="https" class="org.apache.axis2.transport.http.CommonsHTTPTransportSender">
< parameter name="PROTOCOL">HTTP/1.1
< parameter name="Transfer-Encoding">chunked
< !-- This parameter has been added to overcome problems encounted in SOAP action parameter -->
< parameter name="OmitSOAP12Action">true
< / transportSender>
This configuration within the axis2.xml plus the new servlet I've created allows for you to put the ESB behind Apache HTTPD server connected via AJP to tomcat but as mentioned above it does not support switching from a blocking http(s) transport to and non-blocking http(s) transport and vice versa.
Indika,
I will look into allowing blocking and non-blocking communication based on some of the stuff you said above.
Once again thank you for the help.
J