Skip to main content

WSO2: Simple Pass through proxy (REST to REST with HTML Reply)

Today I set out on trying to set up a simple passthrough proxy that would allow for a GET request to be made to REST style backend services that replies with HTML content.

The proxy services was being set up on WS02 ESB v4.8.0.  I thought this was really going to be as simple as walking though their wizard and setting up a new proxy endpoint that just handed off to the behinds the scene service.

It was straight forward to set up the proxy, but then unfortunately when called it just didn't respond. It took quite awhile to figure out what the issues was.  At first I was using the ESB admin console and review the System and Application Logs.  The Application Logs were certainly more useful, but they still truncated stack traces which made it hard to clue in on the real issue.

It wasn't until I went and review the logs on the server that I was able to detect the cause.  

<wso2_esb_root>/repository/logs/wso2-esb-errors.log

2015-03-19 16:09:43,001 [-] [PassThroughMessageProcessor-2] ERROR SequenceMediator Error while building message
org.apache.axis2.AxisFault: Error while building Passthrough stream
        at org.apache.synapse.transport.passthru.util.RelayUtils.handleException(RelayUtils.java:236)
        at org.apache.synapse.transport.passthru.util.RelayUtils.builldMessage(RelayUtils.java:111)
        at org.apache.synapse.transport.passthru.util.RelayUtils.buildMessage(RelayUtils.java:82)
        at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:68)
        at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:47
        at org.apache.synapse.mediators.base.SequenceMediator.mediate(SequenceMediator.java:131)
        at org.apache.synapse.core.axis2.Axis2SynapseEnvironment.injectMessage(Axis2SynapseEnvironment.java:268)
        at org.apache.synapse.core.axis2.SynapseCallbackReceiver.handleMessage(SynapseCallbackReceiver.java:486)
        at org.apache.synapse.core.axis2.SynapseCallbackReceiver.receive(SynapseCallbackReceiver.java:170)
        at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:180)
        at org.apache.synapse.transport.passthru.ClientWorker.run(ClientWorker.java:225)
        at org.apache.axis2.transport.base.threads.NativeWorkerPool$1.run(NativeWorkerPool.java:172)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:724)
Caused by: org.apache.axiom.om.OMException: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[3,59]
Message: DOCTYPE is not allowed
        at org.apache.axiom.om.impl.builder.StAXOMBuilder.next(StAXOMBuilder.java:296)
        at org.apache.axiom.om.impl.llom.OMDocumentImpl.getOMDocumentElement(OMDocumentImpl.java:109)
        at org.apache.axiom.om.impl.builder.StAXOMBuilder.getDocumentElement(StAXOMBuilder.java:570)
        at org.apache.axiom.om.impl.builder.StAXOMBuilder.getDocumentElement(StAXOMBuilder.java:566)
        at org.apache.synapse.transport.passthru.util.DeferredMessageBuilder.getDocument(DeferredMessageBuilder.java:129)
        at org.apache.synapse.transport.passthru.util.RelayUtils.builldMessage(RelayUtils.java:107)
        ... 13 more
Caused by: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[3,59]
Message: DOCTYPE is not allowed
        at com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl.next(XMLStreamReaderImpl.java:598)
        at org.apache.axiom.util.stax.wrapper.XMLStreamReaderWrapper.next(XMLStreamReaderWrapper.java:225)
        at org.apache.axiom.util.stax.dialect.DisallowDoctypeDeclStreamReaderWrapper.next(DisallowDoctypeDeclStreamReaderWrapper.java:34)
        at org.apache.axiom.util.stax.wrapper.XMLStreamReaderWrapper.next(XMLStreamReaderWrapper.java:225)
        at org.apache.axiom.util.stax.dialect.SJSXPStreamReaderWrapper.next(SJSXPStreamReaderWrapper.java:138)
        at org.apache.axiom.om.impl.builder.StAXOMBuilder.parserNext(StAXOMBuilder.java:681)
        at org.apache.axiom.om.impl.builder.StAXOMBuilder.next(StAXOMBuilder.java:214)
        ... 18 more
2015-03-19 16:09:43,004 [-] [PassThroughMessageProcessor-2]  WARN FaultHandler ERROR_CODE : 0
2015-03-19 16:09:43,004 [-] [PassThroughMessageProcessor-2]  WARN FaultHandler ERROR_MESSAGE : Error while building message
2015-03-19 16:09:43,005 [-] [PassThroughMessageProcessor-2]  WARN FaultHandler ERROR_DETAIL : org.apache.synapse.SynapseException: Error while building message
        at org.apache.synapse.mediators.AbstractMediator.handleException(AbstractMediator.java:313)
        at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:70)
        at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:47)
        at org.apache.synapse.mediators.base.SequenceMediator.mediate(SequenceMediator.java:131)
        at org.apache.synapse.core.axis2.Axis2SynapseEnvironment.injectMessage(Axis2SynapseEnvironment.java:268)
        at org.apache.synapse.core.axis2.SynapseCallbackReceiver.handleMessage(SynapseCallbackReceiver.java:486)
        at org.apache.synapse.core.axis2.SynapseCallbackReceiver.receive(SynapseCallbackReceiver.java:170)
        at org.apache.axis2.engine.AxisEngine.receive(AxisEngine.java:180)
        at org.apache.synapse.transport.passthru.ClientWorker.run(ClientWorker.java:225)
        at org.apache.axis2.transport.base.threads.NativeWorkerPool$1.run(NativeWorkerPool.java:172)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:724)
Caused by: org.apache.axis2.AxisFault: Error while building Passthrough stream
        at org.apache.synapse.transport.passthru.util.RelayUtils.handleException(RelayUtils.java:236)
        at org.apache.synapse.transport.passthru.util.RelayUtils.builldMessage(RelayUtils.java:111)
        at org.apache.synapse.transport.passthru.util.RelayUtils.buildMessage(RelayUtils.java:82)
        at org.apache.synapse.mediators.AbstractListMediator.mediate(AbstractListMediator.java:68)
        ... 11 more
Caused by: org.apache.axiom.om.OMException: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[3,59]
Message: DOCTYPE is not allowed
        at org.apache.axiom.om.impl.builder.StAXOMBuilder.next(StAXOMBuilder.java:296)
        at org.apache.axiom.om.impl.llom.OMDocumentImpl.getOMDocumentElement(OMDocumentImpl.java:109)
        at org.apache.axiom.om.impl.builder.StAXOMBuilder.getDocumentElement(StAXOMBuilder.java:570)
        at org.apache.axiom.om.impl.builder.StAXOMBuilder.getDocumentElement(StAXOMBuilder.java:566)
        at org.apache.synapse.transport.passthru.util.DeferredMessageBuilder.getDocument(DeferredMessageBuilder.java:129)
        at org.apache.synapse.transport.passthru.util.RelayUtils.builldMessage(RelayUtils.java:107)
        ... 13 more
Caused by: javax.xml.stream.XMLStreamException: ParseError at [row,col]:[3,59]
Message: DOCTYPE is not allowed
        at com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl.next(XMLStreamReaderImpl.java:598)
        at org.apache.axiom.util.stax.wrapper.XMLStreamReaderWrapper.next(XMLStreamReaderWrapper.java:225)
        at org.apache.axiom.util.stax.dialect.DisallowDoctypeDeclStreamReaderWrapper.next(DisallowDoctypeDeclStreamReaderWrapper.java:34)
        at org.apache.axiom.util.stax.wrapper.XMLStreamReaderWrapper.next(XMLStreamReaderWrapper.java:225)
        at org.apache.axiom.util.stax.dialect.SJSXPStreamReaderWrapper.next(SJSXPStreamReaderWrapper.java:138)
        at org.apache.axiom.om.impl.builder.StAXOMBuilder.parserNext(StAXOMBuilder.java:681)
        at org.apache.axiom.om.impl.builder.StAXOMBuilder.next(StAXOMBuilder.java:214)
        ... 18 more

The default handlers will not handle special tags like   
 <DOCTYPE> , 
<!-- Comment --> 
<?xml tgs for validation and rendering purposes.

You need add or modify the formatters and builders for text/html.  You basically want to make the proxy purely a pass through, simply stream the request and response through the proxy.

Add MessgeFormatter and MessageBuilder

<messagebuilder class="org.apache.axis2.builder.ApplicationXMLBuilder" contenttype="text/html">
      </messagebuilder>
  <messageformatter class="org.apache.axis2.transport.http.ApplicationXMLFormatter" contenttype="text/html">
      </messageformatter>

After adding the message builder and formatter to the axis2.xml config in the ESB the ESB was restarted in order to pick up the new configuration additions.

Then I proceeded with creating the proxy configuration and made sure to include the property

  <property name="FORCE_CONTENT_TYPE_BASED_FORMATTER" value="true" scope="axis2"/>

to insure the the appropriated formatter that was just added gets used for the content return type of "text/html".

The entire proxy configuration source code is below:

 
  <?xml version="1.0" encoding="UTF-8"?>
  <proxy xmlns="http://ws.apache.org/ns/synapse"
       name="asthmaActionPlan"
       transports="http"
       statistics="disable"
       trace="enable"
       startOnLoad="true">
   <target>
      <outSequence>
      <property name="messageType" value="text/html" scope="axis2"/>
         <property name="FORCE_CONTENT_TYPE_BASED_FORMATTER"
                   value="true"
                   scope="axis2"/>
         <send/>
      </outSequence>
      <endpoint>
         <address uri="http://server/web/service/url"/>
      </endpoint>
   </target>
   <description/>
</proxy>  

Then I was able to successfully make a call to the endpoint that passed query parameters in the call and get a response which was a full HTML page.

Comments

  1. Could You Please help fow how to get html payload in expression .Like in JSON we are use json-eval($).

    ReplyDelete
  2. I think this is definitely an amazing project here. So much good will be coming from this project. The ideas and the work behind this will pay off so much. how to learn web development

    ReplyDelete

Post a Comment

Popular posts from this blog

Where to start on AngularJS for Java Developer

Background: If you are a Java developer who is comfortable using Eclipse (JEE Developer version) you may be asking yourself where to start with AngularJS. There is all kinds of documentation out there in regards to AngularJS and https://angularjs.org/ provides, to the point, tutorials on how to get started. You can certainly go that route and use node.js embedded server and possibly a Javascript focused IDE like WebStorm. However I wanted to try and stay in a comfort zone, my comfort zone, of Eclipse and be in a position to deploy an Angular application to a container like Tomcat. This blog entry will present the trail I took to try and accomplish it. Note: This is an adventure into Angular 1.x, not 2.x.  I would imagine this could all work with 2.x as well as it is focused on the dev environment setup. Start: Well the one consistent thing you will find to get started is to install the AngularJS Plugin, provided by Angelo ZERR.  You can use the Eclipse 4.5 (Mar...

Database Leak: getConnection() within Spring Transaction

I recently encountered an issue where one of my teammates was experiencing an issue where an application datasource would periodically become exhausted.  After discussing it a few times, we hypothesized that it was a situation where there was a database connection leak.  It was suspected the leak was within boundaries of some application code with a low call rate.  This would line up with, why the application would run for an extended period and then all of a sudden max out its database connections. By inspecting the logs around the times of the database connection pool becoming exhausted it became pretty clear the potential location of the problematic code. The cause of the issue was not a result of necessarily bad code writing, but more of a case of not knowing how legacy semantics would work within the context of a spring transactional boundary. The semantics of how a call to DataSource.getConnection() behaves within the Spring transaction boundary is probably not ...