Simple Deployment Architecture in Mule
Because there's not predefined architecture that you can apply directly to your projects, choosing an architecture for your system can prove very difficult.
Join the DZone community and get the full member experience.
Join For FreeOne of the biggest challenges in system development is choosing an architecture for the system. There is not a predefined architecture that can be applied directly to your projects. In this article, I would like to discuss a simple Mule deployment architecture.
Problem
First, let's discuss a common problem. For example, in the course of time, your projects and modules have increased in size due to importing lots of external libraries. Let's assume that the size became around gigabytes. Now, the time taken to generate the deployable archive and copy and finally deploying it in Mule Runtime would be enormous. So, in this article, I am going to give a solution to this problem.
Before Starting
Let's discuss how classloaders work in Mule Runtime. Mule has a hierarchy of classloaders. See the diagram below:
At Mule startup, the Java bootstrap classloader will load the necessary classes of the JDK. Then, the Mule system classloader will load the classes present in lib/mule
and lib/opt
directories. The Mule shared domain classloader will load the classes present in each of the domains being used in the applications.
This classloader will search classes in the <lib/shared/domain-name>
directory. And finally, the Mule application classloader will load the classes bundled within the application.
Here is a screenshot of the directories in Mule runtime:
The Magic Trick
It can be seen from the diagram that the Mule shared domain classloader loads the classes that are present in the domains used in the applications. It looks for the classes in the directory <lib/shared/domain-name>
, so this is the key.
For example, our application depends on 100 external libraries (JARs). Now, each time you want to deploy the application in Mule Runtime, you make a ZIP file along with 100 external JARs. The size of the archive will be big and consequently up the time.
The solution to overcoming this problem is to:
Create a domain project and use this domain in the application(s). Let's name the domain as
app-domain
.Now, in Mule Runtime, create a folder under the
lib/shared
directory with the name of the domain created in Step 1, i.e.,lib/shared/app-domain
.Copy all the JARs necessary for the application(s) to the directory created in Step 2.
In the application(s), while generating the deployable ZIP file using Maven, do not bundle the libraries with the application, i.e., use the provided scope in the dependencies in the
pom.xml
.
Now, each time you create the deployable archive (ZIP), the size of the archive will be much smaller and easier to deploy and all the libraries that are copied to the lib/shared/app-domain
directory will be available to all the applications using the domain app-domain
.
System Requirements
The following things are required for the tutorial:
Mule Community Runtime 3.8.1.
Mule Server 3.8.1 CE plugin installed in Anypoint Studio.
The Implementation
The complete source can be found in the repository.
The Parent Pom Project
I have a parent pom project where I am declaring all the dependencies necessary for the projects related to app-domain
. Let's suppose that our applications in app-domain
will depend on only one JAR (common-jar.jar
). Here is the pom.xml:
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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>com.anupam</groupId>
<artifactId>app-dependency-domain</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<mule.version>3.8.1</mule.version>
<mule.tools.version>1.2</mule.tools.version>
</properties>
<dependencies>
<dependency>
<groupId>com.anupam</groupId>
<artifactId>common-jar</artifactId>
<version>1.0.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<!-- Build Mule Domain Project -->
<plugin>
<groupId>org.mule.tools.maven</groupId>
<artifactId>mule-domain-maven-plugin</artifactId>
<version>1.2</version>
<extensions>true</extensions>
<configuration>
<!-- if MULE_HOME variable is configured then the domain will be copy
to domains directory of your mule installation -->
<copyToDomainsDirectory>true</copyToDomainsDirectory>
</configuration>
</plugin>
<!-- Mule Projects -->
<plugin>
<groupId>org.mule.tools.maven</groupId>
<artifactId>mule-app-maven-plugin</artifactId>
<version>${mule.tools.version}</version>
<extensions>true</extensions>
<configuration>
<copyToAppsDirectory>true</copyToAppsDirectory>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>add-resource</id>
<phase>generate-resources</phase>
<goals>
<goal>add-resource</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>src/main/app/</directory>
</resource>
<resource>
<directory>mappings/</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<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>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>mulesoft-release</id>
<name>mulesoft release repository</name>
<layout>default</layout>
<url>http://repository.mulesoft.org/releases/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>
Note that the scope of the dependency is provided. It means that the dependency will not be bundled with the final archive.
Note: I have copied the common-jar
to lib/shared/app-domain
.
The Domain Project
Now I have created a domain project named app-domain. Here is the pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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>com.anupam</groupId>
<artifactId>app-domain</artifactId>
<packaging>mule-domain</packaging>
<version>1.0.0</version>
<name>Domain app-domain Project</name>
<parent>
<groupId>com.anupam</groupId>
<artifactId>app-dependency-domain</artifactId>
<version>1.0.0</version>
</parent>
</project>
We are doing nothing here except declaring the parent
pom. In fact, it is not necessary, as we are not using any library in the domain project.
Projects Using the Domain Project
I have created two projects: app-one and app-two. In both of the projects, I have declared the parent
project. The dependencies declared in the parent
project (common-jar
) will be automatically imported to app-one
andapp-two
.
app-one
In the app-one project, I have declared a specific dependency (demo-jar
). Here is the pom.xml:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.anupam</groupId>
<artifactId>app-one</artifactId>
<version>1.0.0</version>
<packaging>mule</packaging>
<name>Mule app-one Application</name>
<!-- Parent -->
<parent>
<groupId>com.anupam</groupId>
<artifactId>app-dependency-domain</artifactId>
<version>1.0.0</version>
</parent>
<!-- Mule Dependencies -->
<dependencies>
<dependency>
<groupId>com.anupam</groupId>
<artifactId>demo-jar</artifactId>
<version>1.0.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
You can see that I have put the dependency scope as compile
. This means that the JAR will be bundled with the app-one
deployable archive.
app-two
This is a simple project without any extra dependencies. It's just using the common dependency inherited from its parent
. Here is the pom.xml:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.anupam</groupId>
<artifactId>app-two</artifactId>
<version>1.0.0</version>
<packaging>mule</packaging>
<name>Mule app-two Application</name>
<!-- Parent -->
<parent>
<groupId>com.anupam</groupId>
<artifactId>app-dependency-domain</artifactId>
<version>1.0.0</version>
</parent>
<!-- Mule Dependencies -->
<dependencies></dependencies>
</project>
Deployment
Create the deployables for each of the projects (app-domain
, app-one
, and app-two
) using the mvn install
command. Deploy the domain in the domains
directory of Mule Runtime. Please note that it should have the exact name as app-domain
. Remove the version information if there is any. Copy the app-one
andapp-two
ZIPs to the apps
directory and that's it.
If Mule Runtime is running, it will deploy the applications properly. To check the applications, just hit the URLs http://localhost:8081/app1 and http://localhost:8081/app2.
Opinions expressed by DZone contributors are their own.
Comments