Mule 4 is a powerhouse for integration, but every now and then, you encounter a requirement that feels like a missing puzzle piece. One common example? Generating QR Codes.
Currently, MuleSoft does not provide a native "drag-and-drop" connector to create these 2D barcodes. But here is the good news: since Mule runs on the Java Virtual Machine (JVM), we can easily "borrow" capabilities from the Java ecosystem.
In this guide, we will use the popular ZXing ("Zebra Crossing") library to build a custom solution that converts text into a scannable PNG image—all within your Mule flow.
Core Concept: The Java Bridge
Think of MuleSoft as your project manager and Java as the specialist. Mule handles the flow of data, but when it needs to do something complex like image manipulation, it delegates the task to Java.
We are going to build a simple "bridge":
- Mule receives a text string (e.g., a URL or ID).
- Mule passes that string to a custom Java class.
- Java (using ZXing) draws the QR code and converts it into a Base64 string.
- Mule takes that string and converts it back into a standard image file.
Implementation Steps
Follow these steps to build your own QR code generator.
Step 1: The Java Engine
First, we need the logic that does the heavy lifting. We will create a Java class that accepts text and dimensions, creates a bit-matrix (the dots of the QR code), and converts it into a PNG.
Create a file named GenerateQrCode.java inside your project's src/main/java/com/utils folder.
package com.utils;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Base64;
import javax.imageio.ImageIO;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
public class GenerateQrCode {
// Static function that creates QR Code
public static String generateQRcode(String data, int heightOfQR, int widthOfQR) throws WriterException, IOException {
String charset = "UTF-8";
// The BitMatrix class represents the 2D matrix of bits
// MultiFormatWriter is a factory that finds the appropriate Writer subclass for the BarcodeFormat requested
BitMatrix matrix = new MultiFormatWriter().encode(
new String(data.getBytes(charset), charset),
BarcodeFormat.QR_CODE,
widthOfQR,
heightOfQR
);
// Converting BitMatrix to PNG
String imageString = null;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
try {
ImageIO.write(MatrixToImageWriter.toBufferedImage(matrix), "png", bos);
byte[] imageBytes = bos.toByteArray();
// Convert PNG to Base64 String so it can be easily passed back to Mule
Base64.Encoder encoder = Base64.getEncoder();
imageString = encoder.encodeToString(imageBytes);
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
// Return Base64 String to Calling Function
return imageString;
}
};
Step 2: Add Dependencies (POM.xml)
Your project needs the ZXing libraries to compile the code above. Open your pom.xml file and add these entries inside the <dependencies> tag.
Note: We need both the core library (for logic) and the javase library (for image handling).
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.3.0</version>
</dependency>
Step 3: Mule Flow Structure
Now, let's configure the Mule flow. You will need three main components:
- HTTP Listener: To trigger the process via a web request.
- Transform Message (Input): To extract the data you want to encode.
- Transform Message (Output): To call the Java class and render the image.
Step 4: Capture the Input
In your first Transform Message component, extract the data query parameter. This allows users to request a QR code dynamically by visiting a URL like http://localhost:8081/qr?data=HelloMule.
%dw 2.0
output application/java
---
// Extract the value of the "data" query parameter
// Default to "Empty" if no parameter is provided
attributes.queryParams.data as String default "Empty"
Step 5: Generate and Convert
This is where the magic happens. In the second Transform Message component, we use DataWeave to invoke our Java method.
We perform three actions here:
- Import the Java class.
- Call the static method
generateQRcodeto get the Base64 string. - Use the
fromBase64function to turn that string into a binary image file.
%dw 2.0
// Import the GenerateQrCode class using the 'java!' prefix
import java!com::utils::GenerateQrCode
// Import binary functions to help with decoding
import * from dw::core::Binaries
// Set output to PNG image so the browser renders it correctly
output image/png with binary
// Capture the payload from the previous step
var data = payload
var heightOfQR = 300
var widthOfQR = 300
---
// 1. Call Java to get Base64 string
// 2. Decode Base64 to Binary
// 3. Output as proper image format
fromBase64(GenerateQrCode::generateQRcode(data, heightOfQR, widthOfQR)) as Binary
Conclusion
By leveraging the power of Java within Mule 4, we've bypassed the limitation of missing connectors. You can now deploy this application and hit your HTTP Listener endpoint. Mule will return a crisp, scannable PNG image containing whatever data you passed in!
References: