Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Simple Deployment Architecture in Mule

DZone's Guide to

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.

· Integration Zone
Free Resource

Share, secure, distribute, control, and monetize your APIs with the platform built with performance, time-to-value, and growth in mind. Free 90-day trial of 3Scale by Red Hat

One 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:

Mule Classloaders

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:

Image title

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:

  1.  Create a domain project and use this domain in the application(s). Let's name the domain as app-domain.

  2. 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.

  3. Copy all the JARs necessary for the application(s) to the directory created in Step 2.

  4. 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.

Plugin

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.

Image title

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

Explore the core elements of owning an API strategy and best practices for effective API programs. Download the API Owner's Manual, brought to you by 3Scale by Red Hat

Topics:
mule ,architecture ,tutorial ,deployment

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}