Memcached Component for Mule

This code snippet can be used for Mule application workflows that require the ability to place a serializable object into a memcached or pull a serialized object from memcached.  The component is implemented as an Anypoint custom transformer that uses the payload as the source of the put and the target of the get operations.

Usage

The following xml is an Anypoint application with a workflow that performs a get and a second workflow that performs a put.  Both use an Http inbound endpoint to trigger the memcached operation.  Note that the transformer uses a spring bean to configure an xmemcached client builder (the factory).  Transformer properties are used to define the operation to be performed (put or get), the key value to use in the memcached and memcachedClientBuilder references the xmemcached client builder defined in the spring bean.  For the put operation, the expire property defines the number of seconds to hold the cache entry before it is evicted from memcached.

Sample Anypoint Application XML

<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:http="http://www.mulesoft.org/schema/mule/http"
	xmlns:tracking="http://www.mulesoft.org/schema/mule/ee/tracking" xmlns="http://www.mulesoft.org/schema/mule/core"
	xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
	xmlns:spring="http://www.springframework.org/schema/beans" version="EE-3.5.1"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/ee/tracking http://www.mulesoft.org/schema/mule/ee/tracking/current/mule-tracking-ee.xsd">
	<spring:beans>
		<spring:bean id="memcachedClientBuilder" scope="prototype"
			name="memcachedClientBuilder" class="net.rubyeye.xmemcached.XMemcachedClientBuilder">
			<!-- list of memcached server ports. -->
			<spring:constructor-arg value="192.168.191.129:11211" />
			<spring:property name="connectionPoolSize" value="5"></spring:property>
			<spring:property name="commandFactory">
				<spring:bean class="net.rubyeye.xmemcached.command.BinaryCommandFactory"></spring:bean>
			</spring:property>
			<spring:property name="sessionLocator">
				<spring:bean
					class="net.rubyeye.xmemcached.impl.KetamaMemcachedSessionLocator"></spring:bean>
			</spring:property>
			<spring:property name="transcoder">
				<spring:bean
					class="net.rubyeye.xmemcached.transcoders.SerializingTranscoder" />
			</spring:property>
		</spring:bean>
	</spring:beans>

	<flow name="putFlow" doc:name="putFlow">
		<http:inbound-endpoint exchange-pattern="request-response"
			host="localhost" port="8081" path="put" doc:name="HTTP"/>
        <object-to-string-transformer doc:name="Object to String"/>
		<logger message="#[payload]" level="INFO" doc:name="Logger" />
		<custom-transformer class="org.pdd.memcached.MemcachedTransformer"
			doc:name="Java">
			<spring:property name="operation" value="put" />
			<spring:property name="key" value="abc" />
            <spring:property name="memcachedClientBuilder" ref="memcachedClientBuilder"/>
            <spring:property name="expire" value="30"/>
		</custom-transformer>
	</flow>

	<flow name="getFlow" doc:name="getFlow">
		<http:inbound-endpoint exchange-pattern="request-response"
			host="localhost" port="8082" path="get" doc:name="HTTP" />
		<logger message="#[payload]" level="INFO" doc:name="Logger" />
		<custom-transformer class="org.pdd.memcached.MemcachedTransformer"
			doc:name="Java">
			<spring:property name="operation" value="get" />
			<spring:property name="key" value="abc" />
            <spring:property name="memcachedClientBuilder" ref="memcachedClientBuilder"/>
		</custom-transformer>
	</flow>
</mule>

Cut and paste the Java code below into the Anypoint (or Mule) studio as a new Java class file (in the src directory).

Code


package org.pdd.memcached;

import net.rubyeye.xmemcached.MemcachedClient;
import net.rubyeye.xmemcached.MemcachedClientBuilder;

import org.apache.log4j.Logger;
import org.mule.api.MuleEvent;
import org.mule.api.MuleException;
import org.mule.api.MuleMessage;
import org.mule.api.interceptor.Interceptor;
import org.mule.api.transformer.TransformerException;
import org.mule.config.i18n.MessageFactory;
import org.mule.processor.AbstractInterceptingMessageProcessor;
import org.mule.transformer.AbstractMessageTransformer;
import org.mule.transformer.AbstractTransformer;
import org.springframework.beans.factory.annotation.Autowired;

/**
 * 
 * Get or put a payload using memcached entry referenced by a key value. This
 * requires setting up a Spring Bean in the flow to define the memcached client
 * builder. 
    
		
                
                
                
                
                        
                
                
                        
                
                
                        
                
        
    
 * 
 * 
 * Then configure a custom java transformer in the flow. For instance: 
 		
			
			
            
		
* 
 * 
 * @author peterdunworth
 * 
 */
public class MemcachedTransformer extends AbstractMessageTransformer {

	public static Logger log = Logger.getLogger(MemcachedTransformer.class);

	private static String operator_msg = "operation property must be specified as either get or put";

	private MemcachedClientBuilder memcachedClientBuilder = null;
	// get or put
	private String operation = "get";
	private String key = null;
	private String resultClass = null;
	private String expire = null;
	private int ttl = 54000; // seconds=15min

	public MemcachedClientBuilder getMemcachedClientBuilder() {
		return memcachedClientBuilder;
	}

	public void setMemcachedClientBuilder(
			MemcachedClientBuilder memcachedClientBuilder) {
		this.memcachedClientBuilder = memcachedClientBuilder;
	}

	public String getOperation() {
		return operation;
	}

	public void setOperation(String operation) {
		this.operation = operation.trim().toLowerCase();
	}

	public String getResultClass() {
		return resultClass;
	}

	public void setResultClass(String resultClass) {
		this.resultClass = resultClass;
	}

	public String getKey() {
		return key;
	}

	public void setKey(String key) {
		this.key = key.trim();
	}

	public String getExpire() {
		expire = Integer.toString(ttl);
		return expire;
	}

	public void setExpire(String expire) {
		this.ttl = Integer.parseInt(expire);
		this.expire = expire;
	}

	public int getTtl() {
		return ttl;
	}

	public void setTtl(int ttl) {
		this.ttl = ttl;
	}

	@Override
	public Object transformMessage(MuleMessage message, String encoding)
			throws TransformerException {

		if (memcachedClientBuilder == null) {
			throw new TransformerException(
					MessageFactory
							.createStaticMessage("Missing Spring bean memcachedClientBuilder"));
		}
		if (operation == null || operation.isEmpty()) {
			throw new TransformerException(
					MessageFactory.createStaticMessage(operator_msg));
		}
		if (key == null || key.isEmpty()) {
			throw new TransformerException(
					MessageFactory
							.createStaticMessage("key property must be the cache key value"));
		}
		try {
			MemcachedClient memcachedClient = memcachedClientBuilder.build();

			if (operation.equals("get")) {
				return memcachedClient.get(key);
			} else if (operation.equals("put")) {
				memcachedClient.set(key, ttl, message.getPayload());
				return message.getPayload();
			} else {
				throw new TransformerException(
						MessageFactory.createStaticMessage(operator_msg));
			}
		} catch (TransformerException e) {
			throw e;
		} catch (Exception e) {
			e.printStackTrace();
			throw new TransformerException(
					MessageFactory.createStaticMessage("transformMessage caught Exception: "
							+ e.toString()), e);
		}
	}
}

Eclipse Maven Dependencies

If this code is built in Eclipse instead of Anypoint (Mule) Studio, the following maven dependencies are required. Once built, the jar file can be dropped into the lib folder of the Mule project directory (and the jar file added to the build path).

<project xmlns=”http://maven.apache.org/POM/4.0.0&#8243; xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance&#8221;
xsi:schemaLocation=”http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd”&gt;
<modelVersion>4.0.0</modelVersion>
<groupId>org.pdd.memcached</groupId>
<artifactId>memcached-transformer</artifactId>
<version>0.0.1</version>
<name>memcached transformer</name><properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><mule.version>3.5.0</mule.version>
<eclipsePluginVersion>2.8</eclipsePluginVersion>
<jdkName>JavaSE-1.7</jdkName>
<jdk.version>1.7</jdk.version>
<junit.version>4.9</junit.version>
</properties><build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
<encoding>ISO-8859-1</encoding>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2.1</version>
<configuration>
<descriptorRefs>
<descriptorRef>project</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>

<dependencies>
<dependency>
<groupId>com.googlecode.xmemcached</groupId>
<artifactId>xmemcached</artifactId>
<version>2.0.0</version>
</dependency>

<dependency>
<groupId>org.mule</groupId>
<artifactId>mule-core</artifactId>
<version>${mule.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.mulesoft.muleesb.modules</groupId>
<artifactId>mule-module-boot-ee</artifactId>
<version>${mule.version}</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>org.mule.modules</groupId>
<artifactId>mule-module-spring-config</artifactId>
<version>${mule.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.cloveretl</groupId>
<artifactId>cloveretl-engine</artifactId>
<version>${mule.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

<repositories>
<repository>
<id>Central</id>
<name>Central</name>
<url>http://repo1.maven.org/maven2/</url&gt;
<layout>default</layout>
</repository>
<repository>
<id>mulesoft-releases</id>
<name>MuleSoft Releases Repository</name>
<url>http://repository.mulesoft.org/releases/</url&gt;
<layout>default</layout>
</repository>
<repository>
<id>mulesoft-snapshots</id>
<name>MuleSoft Snapshots Repository</name>
<url>http://repository.mulesoft.org/snapshots/</url&gt;
<layout>default</layout>
</repository>
</repositories>
</project>

Advertisement
Leave a comment

Comments

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: