Archive

Author Archive

How to Remove Links to Twitter, Facebook, … Using a Proxy

June 17, 2011 7 comments

Hi,

you can use the RegExReplaceInterceptor to remove links for example to Twitter and Facebook. It simply replaces parts of the response that matches a regular expression with a replacement string.

On the following site there are links and buttons to Twitter, Facebook and DZone located at the top right corner:

http://predic8.com/rest-webservices.htm

The Twitter and Facebook links use a tags while the DZone markup is generated by a script contained in a script tag. We will use the RegExReplaceInterceptor to remove those tags.

For each tag we want to remove we create a RegExReplaceInterceptor bean definition. You can do it with only one bean definition but than the pattern you use will be more complex. So we add the following bean definitions into our monitor-beans.xml document.

For Facebook:

<bean id="stripFacebook" class="com.predic8.membrane.core.interceptor.RegExReplaceInterceptor">
<property name="displayName" value="Strip Facebook"/>
<property name="pattern" value='&lt;a [^&gt;]*http://www.facebook\.com/sharer\.php.*?&lt;/a&gt;'/>
<property name="replacement" value=""/>
</bean>

For Twitter:

<bean id="stripTwitter" class="com.predic8.membrane.core.interceptor.RegExReplaceInterceptor">
<property name="displayName" value="Strip Twitter"/>
<property name="pattern" value='&lt;a [^&gt;]*http://twitter.com/share.*?&lt;/a&gt;'/>
<property name="replacement" value=""/>
</bean>

For DZone:

<bean id="stripDzone" class="com.predic8.membrane.core.interceptor.RegExReplaceInterceptor">
<property name="displayName" value="Strip DZone"/>
<property name="pattern" value="&lt;script [^&gt;]*http://widgets\.dzone\.com/links/widgets/zoneit\.js.*?&lt;/script&gt;"/>
<property name="replacement" value=""/>
</bean>

The pattern property defines the regular expression that is used. It follows standard Java RegEx Pattern syntax. Every part in the response that matches the regulare expression is replaced by the string defined by the replacement property.
We choose the patterns so that they match the a tag that points to facebook and twitter and the script tag that contains the script for DZone.

Now we need a rule configuration so that the RegExReplaceInterceptors are used. You can use the Membrane Monitor to create a rule and add the interceptors we created above to it or you can use the following rule.xml document:

<configuration>
  <rules>
    <forwarding-rule name="stripFacebookAndCo" port="2000">
      <targetport>80</targetport>
      <targethost>predic8.com</targethost>
      <interceptors>
        <interceptor id="stripDzone"/>
        <interceptor id="stripFacebook"/>
        <interceptor id="stripTwitter"/>
      </interceptors>
    </forwarding-rule>
  </rules>
</configuration>

Start the Router or Monitor with the rules.xml given above and the modifications to the monitor-beans.xml. Than open the following URL:

http://localhost:2000/rest-webservices.htm

You will see the same article as before but without the Twitter, Facebook and DZone links and buttons.

Advertisements

Membrane Router as JBoss Service (MBean)

I had to deploy Membrane Router at a data center but the only deployment options I had were EAR, WAR or SAR (JBoss Service) archives. So I created a JBoss services that wrapped the router. Listing 1 shows the MBean interface for the router service. There are two getter/setter pairs for the routers Spring configuration and the routing rules configuration.

package com.predic8.membrane.core;

public interface RouterServiceMBean {
    public void start() throws Exception;
    public void stop() throws Exception;
	public void setRulesXml(String rulesXml);
	public String getRulesXml();
	public void setMonitorBeansXml(String monitorBeansXml);
	public String getMonitorBeansXml();
}

RouterService implements the RouterServiceMBean. All the magic is in the start method that starts the router.

package com.predic8.membrane.core;

import org.apache.commons.logging.*;

public class RouterService implements RouterServiceMBean {

	private static Log log = LogFactory.getLog(RouterService.class.getName());

	Router router;
	
	private String monitorBeansXml="classpath:monitor-beans.xml";
	private String rulesXml="classpath:rules.xml";
	
    public void start() throws Exception {
    	router = Router.init(monitorBeansXml);
		router.getConfigurationManager().loadConfiguration(rulesXml);
        log.info("Router started");
    }

	public void stop() throws Exception {
        router.getTransport().closeAll();
        log.info("Router stopped");
    }

	public String getMonitorBeansXml() {
		return monitorBeansXml;
	}

	public void setMonitorBeansXml(String monitorBeansXml) {
		this.monitorBeansXml = monitorBeansXml;
	}

	public String getRulesXml() {
		return rulesXml;
	}

	public void setRulesXml(String rulesXml) {
		this.rulesXml = rulesXml;
	}

}

What’s left is a jboss-service.xml that configures the RouterService.

<server>
		<mbean code="com.predic8.membrane.core.RouterService" name="com.predic8:service=RouterService">
			 <attribute name="MonitorBeansXml">classpath:monitor-beans.xml</attribute>			
			 <attribute name="RulesXml">classpath:rules.xml</attribute>			
		</mbean>
</server>

At last we have to put all together with the Membrane libraries into a SAR archive that can be deployed at a JBoss server instance.

Categories: General

Tutorial: Mapping SOAP Operations to REST Resources

May 11, 2011 2 comments

REST 2 SOAP Mapping

In this Tutorial we will see how to use the REST2SOAPInterceptor. It will allow us to call a SOAP Web Service by using REST resource URIs. For example take a look at the BLZService at the following location:

http://www.thomas-bayer.com/axis2/services/BLZService?wsdl

To call the getBank operation you have to send a SOAP message like the following:

<soapenv:Envelope xmlns:soapenv=”http://schemas.xmlsoap.org/soap/envelope/”
   xmlns:blz=”http://thomas-bayer.com/blz/”>
  <soapenv:Header/>
  <soapenv:Body>
    <blz:getBank>
      <blz:blz>37050198</blz:blz>
    </blz:getBank>
  </soapenv:Body>
</soapenv:Envelope>

Now let us imagine that there is a REST resource for banks. Probably the URI to get a representation of a bank will look like this:

http://localhost:2000/bank/37050198

This mapping can be done by the REST2SOAPInterceptor without modifing the SOAP service.

REST2SOAPInterceptor

First we will take a look at how the interceptor works. It is configured by a list of mappings. Each of them contains the information to map HTTP requests to SOAP operations. This allows us to map many SOAP operations with one interceptor. Finding the right mapping for a given HTTP request is done by a regular expression. Every mapping contains a regular expression that is matched against the URL of the HTTP request. The mapping which regular expression matches first is taken. With that mapping the interceptor creates a XML document from the HTTP request.

For example for the  following HTTP request

GET /bank/37050198 HTTP/1.1
Host: www.thomas-bayer.com
User-Agent: Jakarta Commons-HttpClient/3.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive

the interceptor will create the following XML document:

<request method="GET" http-version="1.1">
  <uri value="/bank/37050198">
    <host>www.thomas-bayer.com</host>
    <path>
      <component>bank</component>
      <component>37050198</component>
    </path>
  </uri>
  <headers>
    <header name="User-Agent">Jakarta Commons-HttpClient/3.1</header>
    <header name="Host">www.thomas-bayer.com</header>
  </headers>
</request>

Than a  XSLT transformation is applied to the XML document. The transformation creates the SOAP message for the SOAP operation we want to call. Finally the transformed message is send to the endpoint of the SOAP service. After receiving the response the intercetor can by configured to apply another XSLT transformation to strip the SOAP envelope of the response. The service endpoint and the references to the XSLT stylesheets are defined in the mapping.

RESTfull BLZ Service

  1. Create a stylesheet called blz-httpget2soap-request.xsl. It will be used by the interceptor to create the SOAP message. It should have the following content:
    <xsl:stylesheet version=”1.0″ xmlns:xsl=”http://www.w3.org/1999/XSL/Transform”
      xmlns:s11=”http://schemas.xmlsoap.org/soap/envelope/”
      xmlns:blz=”http://thomas-bayer.com/blz/”>
    
      <xsl:template match=”/”>
        <s11:Envelope >
          <s11:Body>
            <blz:getBank>
              <blz:blz><xsl:value-of select=”//path/component[2]“/></blz:blz>
            </blz:getBank>
          </s11:Body>
        </s11:Envelope>
      </xsl:template>
    </xsl:stylesheet>
    
  2. Create a stylesheet called strip-soap-envelope.xslto strip the SOAP envelope from the response. It should have the following content:
    <xsl:stylesheet version=”1.0″ xmlns:xsl=”http://www.w3.org/1999/XSL/Transform”
      xmlns:s11=”http://schemas.xmlsoap.org/soap/envelope/”>
    
      <xsl:template match=”/”>
        <xsl:apply-templates select=”//s11:Body/*”/>
      </xsl:template>
    
      <xsl:template match=”@*|node()”>
        <xsl:copy>
          <xsl:apply-templates select=”@*”/>
          <xsl:apply-templates/>
        </xsl:copy>
      </xsl:template>
    </xsl:stylesheet>
    
  3. Copy the stylesheets into the configuration folder of your monitor or router installation directory.
  4. Open monitor-beans.xml and add a bean for the REST2SOAP interceptor to the list of interceptors in the transport bean.
    <bean id="transport" class="com.predic8.membrane.core.transport.http.HttpTransport">
      [...]
      <property name="interceptors">
        <list>
          [...]
          <bean class="com.predic8.membrane.core.interceptor.rest.REST2SOAPInterceptor">
            <property name="mappings">
              <map>
                <entry key="/bank/.*">
                  <map>
                    <entry key="SOAPAction" value=""/>
              	<entry key="SOAPURL" value="/axis2/services/BLZService" />
              	<entry key="requestXSLT" value="configuration/blz-httpget2soap-request.xsl" />
              	<entry key="responseXSLT" value="configuration/strip-soap-envelope.xsl" />
                  </map>
                 </entry>
              </map>
            </property>
          </bean>
          [...]
        </list>
      </property>
      [...]
    </bean>
    
  5. Start the Membrane monitor.
  6. Create a rule that listens on port 2000 and redirect requests to thomas-bayer.com:80.
  7. Open the link http://localhost:2000/bank/37050198 in your browser.
Categories: Monitor, Router

Announcement: Upcoming Version 2.0.0 featuring REST and JSON

Hi,

a new major version of the Membrane Monitor and Router will be released. We reworked the core of the router to provide a significantly increased performance and support for REST resources and JSON. Some of the highlights are:

  • A JSON beautifier that formats JSON messages in the Monitor
  • Gateway functionality that bridges between SOAP Web Services and REST resources
  • A XSLTransformer interceptor
  • An improved API that makes it easier to integrate the HTTP router into own Java programs.
  • Lots of minor bug fixes
  • An performance optimized core that can handle hundreds of concurrent connections with just 6MB of heap memory.
  • A JBoss service that makes it possible to deploy the HTTP/SOAP router into a JBoss server.
  • A validator that validates SOAP messages against WSDL definitions and XML Schemas
  • Improved connection handling that reduces the number of used sockets.

We are doing the final tests and hope that the version 2.0.0 will be available for download in a couple of days.

Shaan

Categories: General