Mule Standalone Runtime without Anypoint Studio (Part 3 – building custom connector)

Mule Standalone Runtime without Anypoint Studio (Part 3 – building custom connector)

Welcome back! We will continue to program the ESB bus with Mule. This is the third part of our Mule tutorial without Anypoint tool. We already have an environment, a ready domain module and implemented services (which even work!).

If you want to go back to the previous parts, you can find them here:

Now we’ll do connector programming and finally write something in java code.

According to information from mulesoft website – connector is a reusable component that interacts with Mule runtime. A connector communicates with a target resource and conveys information between a resource and Mule, and transforms the data into a Mule message. A well-developed connector makes Mule app development much simpler for users when handling tasks like pagination, session expirations, and input and output metadata.

At the beginning, we create a primary module (e.g. called „connectors”). All connectors will be kept there. In this module, we can delete everything except the pom.xml file. Only inside this module, we create new modules that will be responsible for individual connectors

Before implementing the code, we need to configure the pom.xml file in connectors module. You need to remove all dependencies from the enterprise version and remove test-related elements (we do what we did when building the previous modules). Mulesoft is very closely associated with the eclipse brand, so we have a lot of work to do to properly configure our environment. The pom.xml file in the „connectors” module must be defined as the packaging type pom, while in the secondary connectors – pom.xml must be of the mule-module packaging type.

The contents of the pom.xml file from the main connectors module will be inherited by all child modules – a lot of configuration awaits us here, and then it will be much easier 🙂

Here is the content of dependencies in main pom.xml located in connectors module. This is a parent POM for use in Mule extensions based on the Mule SDK. It provides several defaults that make managing and building connectors easier.

    <scm>
        <connection>scm:git:git://github.com:mulesoft/mule-devkit-parent.git</connection>
        <developerConnection>scm:git:git@github.com:mulesoft/mule-devkit-parent.git</developerConnection>
        <url>http://github.com/mulesoft/mule-devkit-parent</url>
    </scm>

    <dependencies>
        <!-- Mule Dependencies -->
        <dependency>
            <groupId>org.mule</groupId>
            <artifactId>mule-core</artifactId>
            <version>3.9.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.mule.tools.devkit</groupId>
            <artifactId>mule-devkit-annotations</artifactId>
            <version>3.9.0</version>
            <scope>provided</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.apache.logging.log4j</groupId>
                    <artifactId>log4j-api</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.mule.modules</groupId>
            <artifactId>mule-module-spring-config</artifactId>
            <version>3.9.0</version>
            <optional>true</optional>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.mule.modules</groupId>
            <artifactId>mule-module-devkit-support</artifactId>
            <version>3.9.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.mule.modules</groupId>
            <artifactId>mule-module-json</artifactId>
            <version>3.9.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.mule.modules</groupId>
            <artifactId>mule-module-ws</artifactId>
            <version>${mule.version}</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

Explanation of individual dependencies from above fragment:

  • scm area – file source definition
  • mule-core – basic mule libraries
  • mule-devkit-annotations – core Java annotations
  • mule-module-spring-config – Mule Builder for use with Spring
  • mule-module-devkit-support – Interfaces and classes required by Devkit
  • mule-module-json – Implementation of JSON transformers for Mule
  • mule-module-ws – Provides components for working with Web Services.

The second important thing in pom.xml implementation for connectors module is the build area. We have to add specific plugins and profiles. The content of this code was taken from the official repository provided by mulesoft (https://github.com/mulesoft/mule-extensions-parent/blob/master/pom.xml)

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                    <groupId>org.mule.tools.devkit</groupId>
                    <artifactId>mule-devkit-maven-plugin</artifactId>
                    <version>3.9.0</version>
                    <extensions>true</extensions>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.18.1</version>
                    <configuration>
                        <enableAssertions>false</enableAssertions>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>com.mycila</groupId>
                    <artifactId>license-maven-plugin</artifactId>
                    <version>2.11</version>
                    <configuration>
                        <header>LICENSE_HEADER.txt</header>
                        <excludes>
                            <exclude>**/.mule/*</exclude>
                            <exclude>target/**</exclude>
                            <exclude>**/.idea/*</exclude>
                            <exclude>**/.gitignore</exclude>
                            <exclude>**/*.txt</exclude>
                            <exclude>**/*.ftl</exclude>
                            <exclude>**/*.xml</exclude>
                            <exclude>**/*.properties</exclude>
                            <exclude>**/*.wsdl</exclude>
                            <exclude>**/*.xsd</exclude>
                            <exclude>**/*.grf</exclude>
                            <exclude>**/*.sample</exclude>
                            <exclude>**/*.md</exclude>
                            <exclude>**/build-number.txt</exclude>
                        </excludes>
                    </configuration>
                </plugin>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>2.8.2</version>
                </plugin>
            </plugins>
        </pluginManagement>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <executions>
                    <execution>
                        <id>default-compile</id>
                        <configuration>
                            <source>1.8</source>
                            <target>1.8</target>
                        </configuration>
                    </execution>
                    <execution>
                        <id>default-testCompile</id>
                        <configuration>
                            <source>1.8</source>
                            <target>1.8</target>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.18.1</version>
            </plugin>
            <plugin>
                <groupId>org.mule.tools.devkit</groupId>
                <artifactId>mule-devkit-maven-plugin</artifactId>
                <version>3.9.0</version>
                <dependencies>
                    <dependency>
                        <groupId>org.apache.logging.log4j</groupId>
                        <artifactId>log4j-slf4j-impl</artifactId>
                        <version>2.8.2</version>
                    </dependency>
                </dependencies>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.4.1</version>
                <configuration>
                    <!-- devkit shade base configuration -->
                    <artifactSet>
                        <includes combine.children="append">
                            <include>org.mule.tools.devkit:mule-devkit-shade</include>
                        </includes>
                    </artifactSet>
                    <createDependencyReducedPom>false</createDependencyReducedPom>
                    <relocations combine.children="append">
                        <relocation>
                            <pattern>org.mule.devkit.internal</pattern>
                            <shadedPattern>org.mule.devkit.3.9.0.internal</shadedPattern>
                        </relocation>
                        <relocation>
                            <pattern>org.mule.devkit.api</pattern>
                            <shadedPattern>org.mule.devkit.3.9.0.api</shadedPattern>
                        </relocation>
                    </relocations>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
                <version>2.4</version>
                <executions>
                    <execution>
                        <id>attach-sources</id>
                        <goals>
                            <goal>jar-no-fork</goal>
                        </goals>
                        <phase>prepare-package</phase>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <version>2.7</version>
                <configuration>
                    <!-- Avoid invalid resources filtering when using custom licenses -->
                    <nonFilteredFileExtensions>
                        <nonFilteredFileExtension>lic</nonFilteredFileExtension>
                        <nonFilteredFileExtension>key</nonFilteredFileExtension>
                    </nonFilteredFileExtensions>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.apache.maven.shared</groupId>
                        <artifactId>maven-filtering</artifactId>
                        <version>1.3</version>
                    </dependency>
                </dependencies>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-site-plugin</artifactId>
                <version>3.4</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-release-plugin</artifactId>
                <configuration>
                    <autoVersionSubmodules>true</autoVersionSubmodules>
                    <pushChanges>false</pushChanges>
                </configuration>
                <version>2.5.2</version>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-enforcer-plugin</artifactId>
                <version>1.4</version>
                <configuration>
                    <failFast>true</failFast>
                    <rules>
                        <requireJavaVersion>
                            <version>[1.7,1.9)</version>
                        </requireJavaVersion>
                    </rules>
                </configuration>
            </plugin>
        </plugins>
        <resources>
            <resource>
                <filtering>false</filtering>
                <directory>src/main/resources</directory>
            </resource>
        </resources>
        <testResources>
            <testResource>
                <filtering>true</filtering>
                <directory>src/test/resources</directory>
            </testResource>
        </testResources>
        <extensions>
            <extension>
                <groupId>org.apache.maven.wagon</groupId>
                <artifactId>wagon-ssh</artifactId>
                <version>1.0</version>
            </extension>
        </extensions>
    </build>

    <profiles>
        <profile>
            <id>sonar</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <properties>
                <sonar.exclusions>
                    target/**
                </sonar.exclusions>
            </properties>
        </profile>

        <profile>
            <id>apidoc-generator</id>
            <activation>
                <activeByDefault>false</activeByDefault>
                <property>
                    <name>generateApidocs</name>
                </property>
            </activation>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-javadoc-plugin</artifactId>
                        <version>2.10.3</version>
                        <configuration>
                            <reportOutputDirectory>${project.build.directory}/apidocs</reportOutputDirectory>
                            <destDir>javadocs</destDir>
                            <excludePackageNames>
                                *.generated.*:
                                *.tooling.ui.contribution
                            </excludePackageNames>
                            <tags>
                                <tag>
                                    <name>javadoc.url</name>
                                </tag>
                                <tag>
                                    <name>api.doc</name>
                                </tag>
                            </tags>
                        </configuration>
                        <executions>
                            <execution>
                                <id>build-distros</id>
                                <phase>compile</phase>
                                <goals>
                                    <goal>javadoc</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>

        <profile>
            <id>update-site</id>
            <properties>
                <devkit.studio.package.skip>false</devkit.studio.package.skip>
            </properties>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.mule.tooling</groupId>
                        <artifactId>studio-us-signer</artifactId>
                        <version>1.4.1</version>
                        <executions>
                            <execution>
                                <phase>install</phase>
                                <goals>
                                    <goal>sign-us</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>

        <profile>
            <id>strict-validation</id>
            <activation>
                <activeByDefault>false</activeByDefault>
            </activation>
            <properties>
                <show.warnings>true</show.warnings>
            </properties>
            <build>
                <plugins>
                    <plugin>
                        <groupId>com.mycila</groupId>
                        <artifactId>license-maven-plugin</artifactId>
                        <version>2.11</version>
                        <executions>
                            <execution>
                                <phase>validate</phase>
                                <goals>
                                    <goal>check</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                    <plugin>
                        <groupId>org.mule.tools.devkit</groupId>
                        <artifactId>mule-devkit-maven-plugin</artifactId>
                        <version>3.9.0</version>
                        <executions>
                            <execution>
                                <phase>compile</phase>
                                <goals>
                                    <goal>ensure-javadoc</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>


        <profile>
            <id>testdata-generator</id>
            <activation>
                <activeByDefault>false</activeByDefault>
            </activation>

            <dependencies>
                <dependency>
                    <groupId>org.mule.tools.devkit</groupId>
                    <artifactId>testdata-apt-core</artifactId>
                    <version>2.0.5</version>
                </dependency>
            </dependencies>

            <properties>
                <annotations-file>${project.build.directory}/generated-sources/apt/testdata-annotations-output.xml</annotations-file>
            </properties>

            <build>
                <plugins>
                    <plugin>
                        <groupId>org.bsc.maven</groupId>
                        <artifactId>maven-processor-plugin</artifactId>
                        <version>2.2.4</version>
                        <executions>
                            <execution>
                                <id>process</id>
                                <goals>
                                    <goal>process</goal>
                                </goals>
                                <configuration>
                                    <processors>
                                        <processor>com.mule.connectors.testdata.TestDataAnnotationsProcessor</processor>
                                    </processors>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
        <profile>
            <id>only-eclipse</id>
            <activation>
                <property>
                    <!-- This property is defined by m2e IDE and it is the only scenario where this should work -->
                    <name>m2e.version</name>
                </property>
            </activation>
            <build>
                <pluginManagement>
                    <plugins>
                        <plugin>
                            <groupId>org.eclipse.m2e</groupId>
                            <artifactId>lifecycle-mapping</artifactId>
                            <version>1.0.0</version>
                            <configuration>
                                <lifecycleMappingMetadata>
                                    <pluginExecutions>
                                        <pluginExecution>
                                            <pluginExecutionFilter>
                                                <groupId>org.mule.tools.devkit</groupId>
                                                <artifactId>mule-devkit-maven-plugin</artifactId>
                                                <versionRange>[2.0,)</versionRange>
                                                <goals>
                                                    <goal>attach-test-resources</goal>
                                                    <goal>filter-resources</goal>
                                                    <goal>generate-sources</goal>
                                                </goals>
                                            </pluginExecutionFilter>
                                            <action>
                                                <ignore />
                                            </action>
                                        </pluginExecution>
                                        <pluginExecution>
                                            <pluginExecutionFilter>
                                                <artifactId>cxf-codegen-plugin</artifactId>
                                                <groupId>org.apache.cxf</groupId>
                                                <versionRange>[2.3.0,)</versionRange>
                                                <goals>
                                                    <goal>wsdl2java</goal>
                                                </goals>
                                            </pluginExecutionFilter>
                                            <action>
                                                <ignore />
                                            </action>
                                        </pluginExecution>
                                    </pluginExecutions>
                                </lifecycleMappingMetadata>
                            </configuration>
                        </plugin>
                    </plugins>
                </pluginManagement>
            </build>
        </profile>
    </profiles>

Connector Devkit provides various annotations to make developer life easier to build and publish connectors faster. When we have all the above libraries attached and we have managed to sync the project, we go to the implementation of the code in Java. Preparing this tool for work is not an easy task, so if you encounter any errors, feel free to write here in the comment – I will try to help you.

Let’s start with the FirstConnectorConfig Java class. This class is all about setting up the connection with the target system and managing the connection. The value we provide in the friendlyName attribute in @Configuration annotation gets displayed at the top of the connector configuration.

import org.mule.api.annotations.components.Configuration;

@Configuration(friendlyName = "Configuration")
public class FirstConnectorConfig {
    // TO DO
}

Formerly, a configuration using Connection Management DevKit Annotations was used, but now it is obsolete (as indicated by the manufacturer himself) and recommends a different way of defining the connector configuration.

Now, let’s take a look at the FirstConnector Java class. In this class, we define operations and write logic to perform those operations. Depending on the connector functionality, it could be anything from a CRUD operation to a more sophisticated functionality offering. We can also add the logger so that custom connectors would be able to log its data onto the Mule log.

import com.oskarro.config.FirstConnectorConfig;
import lombok.extern.slf4j.Slf4j;
import org.mule.api.MuleEvent;
import org.mule.api.annotations.Config;
import org.mule.api.annotations.Connector;
import org.mule.api.annotations.ContainsTransformerMethods;
import org.mule.api.annotations.Processor;
import org.mule.api.annotations.lifecycle.Start;

@Connector(name = "first-connector", friendlyName = "First Connector")
@ContainsTransformerMethods
@Slf4j
public class FirstConnector {

    @Config
    private FirstConnectorConfig config;

    @Start
    public void init() {
        log.info("Connector {} has been initialized.", FirstConnector.class.getSimpleName());
    }

    public FirstConnectorConfig getConfig() {
        return config;
    }

    public void setConfig(FirstConnectorConfig config) {
        this.config = config;
    }
}

Here, friendlyName attribute value gets displayed in the connector details section. @Processor — Marks a method as an operation in a connector.

@Processor
public String printMessage(MuleEvent event) {
    return "New payload";
}

The last return line is important – if you return a string or anything else besides an event it will overwrite any payload that passes through your connectors. If this is not what you want then you should return an event instead.

Write a comment