Mule 4 will be released soon. Along with Mule 4 a new Mule SDK is relased which can be used to extend the functionality of Mule with custom modules. The Mule SDK replaces Devkit for developing connectors.

Documentation on the Mule SDK can so far be found on the About the Mule SDK page.

The Mule SDK is not tightly bound to Anypoint Studio in the same way that Devkit is. The custom modules is hooking into the Mule Runtime by annotations and class inheritance. Instead of having to install the custom module in Anypoint Studio, you just have to add it as a Maven dependency.

Setting up a project

A maven archetype is provided as a starting point. At the moment it has some flaws. Looking for newer versions of the archetype is probably a good idea.

The archetype project can be found on the project github page.

mvn archetype:generate -DarchetypeGroupId=org.mule.extensions -DarchetypeArtifactId=mule-extensions-archetype -DarchetypeVersion=1.2.0-SNAPSHOT -DgroupId=com.redpilllinpro.mule.demo -DartifactId=rplp-extension -DextensionName=RPLP

This creates a Maven project structure with an example component and unit test.

The connector

A custom connector consist of a number of classes connected with annotations.

The extension is defined by a class with the Extension annotation. A Configurations annotation points to the main configuration class.

package com.redpilllinpro.mule.demo;

import org.mule.runtime.extension.api.annotation.Extension;
import org.mule.runtime.extension.api.annotation.Configurations;
import org.mule.runtime.extension.api.annotation.dsl.xml.Xml;

@Xml(prefix = "rplp")
@Extension(name = "RPLP")
public class RPLPExtension {

A configuration class defines the parameters that are to be defined in the config element of the module. By using the Operations and ConnectionProviders annotations this class also points to the operations that the extenstion implements and to the connection providers.

package com.redpilllinpro.mule.demo;

import org.mule.runtime.extension.api.annotation.Operations;
import org.mule.runtime.extension.api.annotation.connectivity.ConnectionProviders;
import org.mule.runtime.extension.api.annotation.param.Parameter;

public class RPLPConfiguration {

  private String configId;

  public String getConfigId(){
    return configId;

A connection provider implements one of the supplied connection providers, in this case PoolingConnectionProvider. Other options are CachedConnectionProvider and ConnectionProvider. The connect, disconnect and validate methods are overridden to provide functionality specific to this connection. Parameters specified in this class with the Parameter annotation are used as parameters to the connection in the config element of the component.

package com.redpilllinpro.mule.demo;

import org.mule.runtime.api.connection.ConnectionException;
import org.mule.runtime.extension.api.annotation.param.Parameter;
import org.mule.runtime.extension.api.annotation.param.Optional;
import org.mule.runtime.api.connection.ConnectionValidationResult;
import org.mule.runtime.api.connection.PoolingConnectionProvider;
import org.mule.runtime.api.connection.ConnectionProvider;
import org.mule.runtime.api.connection.CachedConnectionProvider;
import org.mule.runtime.extension.api.annotation.param.display.DisplayName;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RPLPConnectionProvider implements PoolingConnectionProvider<RPLPConnection> {

  private final Logger LOGGER = LoggerFactory.getLogger(RPLPConnectionProvider.class);

  @Optional(defaultValue = "localhost")
  private String hostname;

  @Optional(defaultValue = "RPLPQueue")
  private String queueName;

  public RPLPConnection connect() throws ConnectionException {
    return new RPLPConnection(hostname, queueName);

  public void disconnect(RPLPConnection connection) {
    try {
    } catch (Exception e) {
      LOGGER.error("Error while disconnecting [" + connection.getId() + "]: " + e.getMessage(), e);

  public ConnectionValidationResult validate(RPLPConnection connection) {
	  ConnectionValidationResult result;
		  result = ConnectionValidationResult.success();
	  } else {
		  result = ConnectionValidationResult.failure("Connection failed " + connection.getId(), new Exception());

    return result;

A connection class is used by the connection provider to handle the details of the configuration, in this case a connection to a RabbitMQ.

package com.redpilllinpro.mule.demo;


import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

public final class RPLPConnection {
	private final Logger LOGGER = LoggerFactory.getLogger(RPLPConnection.class);

	private ConnectionFactory factory = new ConnectionFactory();
	private Connection connection;
	private Channel channel;
	private String queueName;

	public void publish(byte[] payload){
		try {
			channel.basicPublish("", queueName, null, payload);
		} catch (IOException e) {
			LOGGER.error("Coop Governance logging failed. " + e.getMessage());

  public RPLPConnection(String hostname, String queueName) {
	  this.queueName = queueName;
	  try {
			connection = factory.newConnection();
			channel = connection.createChannel();
		} catch (Exception e) {
			channel = null;
			connection = null;
			LOGGER.error("Coop Governance logging connection failed. " + e.getMessage());

  public String getId() {
	  if (connection != null){
  		return String.valueOf(connection.hashCode());
  	}else {
  		return "No connection";

  public void disconnect() {
	  try {
		} catch (Exception e) {
			LOGGER.warn("Queue disconnect failed. " + e.getMessage());
		} finally {
			channel = null;
			connection = null;

	public boolean isConnected(){
		return channel != null;

Finally the operations that the component offers are defined as public methods in an operations class.

package com.redpilllinpro.mule.demo;

import static org.mule.runtime.extension.api.annotation.param.MediaType.ANY;

import org.mule.runtime.extension.api.annotation.param.MediaType;
import org.mule.runtime.extension.api.annotation.param.Config;
import org.mule.runtime.extension.api.annotation.param.Connection;

public class RPLPOperations {

	@MediaType(value = ANY, strict = false)
	public void publish(@Config RPLPConfiguration configuration, @Connection RPLPConnection connection, String message){
		message = configuration.getConfigId() +": "+ message;


The Mule flow

To use the new component in a Mule project, add a dependency to the component in the Mule project pom; remember the classifier.


The new component will appear in the Mule Palette and can be used in flows.

<?xml version="1.0" encoding="UTF-8"?>

<mule xmlns:http="" xmlns:rplp=""
	xmlns:doc="" xmlns:xsi="" xsi:schemaLocation="">
	<rplp:config name="RPLP_Config" doc:name="RPLP Config" configId="id2">
	<http:listener-config name="HTTP_Listener_config" doc:name="HTTP Listener config">
		<http:listener-connection port="8081" host=""/>
	<flow name="rplp-demoFlow">
		<http:listener doc:name="Listener" config-ref="HTTP_Listener_config" path="/rplp"/>
		<rplp:publish doc:name="Publish" config-ref="RPLP_Config" message="#[payload]"/>

Morten Furbo Skødt Nielsen

Integration Consultant at Redpill Linpro

Morten Furbo works as an integration specialist and Java developer from our office in Copenhagen, creating integrations in Mule for various customers.

Layer 3 routing on Cumulus Linux MLAG

We build our network in order to simultaneously achieve high availability and maximum utilisation of available bandwidth. To that end, we are using Multi-Chassis Link Aggregation (MLAG) between our data centre switches running Cumulus Linux and our firewall cluster «on a stick»:

MLAG topology

fw1 is tricked into believing it is dual connected to a single device that speaks the IEEE 802.3ad Link Aggregation Control Protocol. This works great for layer 2 and ... [continue reading]

Jenkinsfile to Anypoint platform and Artifactory

Published on January 26, 2018

Mulesoft Runtime on Raspberry with Kubernetes

Published on January 23, 2018