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).
xsi:schemaLocation=”http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd”>
<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>
<layout>default</layout>
</repository>
<repository>
<id>mulesoft-releases</id>
<name>MuleSoft Releases Repository</name>
<url>http://repository.mulesoft.org/releases/</url>
<layout>default</layout>
</repository>
<repository>
<id>mulesoft-snapshots</id>
<name>MuleSoft Snapshots Repository</name>
<url>http://repository.mulesoft.org/snapshots/</url>
<layout>default</layout>
</repository>
</repositories>
</project>