mvn archetype:generate \
-DgroupId=org.example.agent \
-DartifactId=mule-agent-hello-validator \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DinteractiveMode=false
Application Validator Service
Where possible, we changed noninclusive terms to align with our company value of Equality. We maintained certain terms to avoid any effect on customer implementations. |
The Application Validator Service enables you to create your own custom validators that prevent your application from being deployed if certain conditions are not met. Depending on the Mule Runtime Agent configuration, the service invokes your custom validators to enforce business rules, such as signing validation, naming conventions, or moratorium dates.
Create an Application Validator
Follow these steps to create a custom validator that checks the value of an application property and stops the deployment if the property does not meet the specified criteria:
Create a Maven Project
Open a terminal, navigate to the folder where you want to create the Java project, and type the following command:
Maven Directory Layout
The previous command creates the following project directory structure:
./mule-agent-hello-validator
./mule-agent-hello-validator/pom.xml
./mule-agent-hello-validator/src
./mule-agent-hello-validator/src/test
./mule-agent-hello-validator/src/test/java
./mule-agent-hello-validator/src/test/java/org
./mule-agent-hello-validator/src/test/java/org/example
./mule-agent-hello-validator/src/test/java/org/example/agent
./mule-agent-hello-validator/src/test/java/org/example/agent/AppTest.java
./mule-agent-hello-validator/src/main
./mule-agent-hello-validator/src/main/java
./mule-agent-hello-validator/src/main/java/org
./mule-agent-hello-validator/src/main/java/org/example
./mule-agent-hello-validator/src/main/java/org/example/agent
./mule-agent-hello-validator/src/main/java/org/example/agent/App.java
Create the Project Object Model (POM) File
Create a POM file with the following configuration details:
Properties
-
Access the generated folder and locate the generated
pom.xml
file. -
Add the following properties:
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<mule.agent.version>2.4.28</mule.agent.version>
<javax.servlet-api.version>3.1.0</javax.servlet-api.version>
<javax.ws.version>2.0</javax.ws.version>
<log4j.version>2.17.1</log4j.version>
<guice.version>5.0.1</guice.version>
<javax.inject.version>1</javax.inject.version>
</properties>
The previous properties represent the versions used for the following required dependencies:
|
Java API for the Mule Agent Plugin |
|
Java API for RESTful Web Services |
|
Java Servlet API |
|
The javax.inject API |
|
Google Guice Core Library |
|
The Apache Log4j API |
Dependencies
Add the com.mulesoft.agent:mule-agent-api
dependency:
<dependency>
<groupId>com.mulesoft.agent</groupId>
<artifactId>mule-agent-api</artifactId>
<version>${mule.agent.version}</version>
<scope>provided</scope>
</dependency>
Add the javax.ws.rs:javax.ws.rs-api
dependency:
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
<version>${javax.ws.version}</version>
</dependency>
Add the javax.servlet:javax.servlet-api
dependency:
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>${javax.servlet-api.version}</version>
</dependency>
Add the javax.inject:javax.inject
dependency:
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
<version>${javax.inject.version}</version>
</dependency>
Add the com.google.inject:guice
dependency:
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>${guice.version}</version>
</dependency>
Add the log4j
dependencies:
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>${log4j.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>${log4j.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>${log4j.version}</version>
<scope>compile</scope>
</dependency>
Repositories
Add the MuleSoft releases and snapshots repositories:
<repositories>
<repository>
<id>mulesoft-ci-releases</id>
<name>Mulesoft Release Repository</name>
<url>https://repository-master.mulesoft.org/nexus/content/repositories/releases-ee/</url>
</repository>
<repository>
<id>mulesoft-ci-snapshots</id>
<name>MuleSoft Snapshot Repository</name>
<url>https://repository-master.mulesoft.org/nexus/content/repositories/ci-snapshots/</url>
</repository>
</repositories>
Create the Validator Class
-
Rename the default class to
MuleAgentHelloValidator
:Before:
mule-agent-hello-validator/src/main/java/org/example/App.java
After:
mule-agent-hello-validator/src/main/java/org/example/MuleAgentHelloValidator.java
-
Add the following annotations:
@Named("MuleAgentHelloValidator") @Singleton
-
Add the following property to obtain a named logger based on the validator class:
private static final Logger LOGGER = LogManager.getLogger(MuleAgentHelloWorld.class);
-
Implement the artifact validator interface:
public class MuleAgentHelloWorld implements ApplicationValidator { private static final Logger LOGGER = LogManager.getLogger(MuleAgentHelloWorld.class); // Type represents a group of validator implementations public String getType() { return "helloValidator"; } // Custom name for the implementation. // Represent a specific use case related to the validator type // Must be unique in the type. public String getName() { return "defaultHelloValidator"; } public void validate(Map<String, Object> args) throws ArtifactValidationException { } }
-
Add the
args
parameter, which contains the validator configuration provided in themule-agent.yml
file:services: mule.agent.artifact.validator.service: enabled: true validators: - type: helloValidator name: defaultHelloValidator enabled: true args: business: finance welcomeMessage: 'Hi, welcome to Finance Cluster Runtimes' errorMessage: 'I am sorry, you are not allowed to deploy in this Cluster'
It also contains the following values that are injected by the service:
Key | Description |
---|---|
|
A string value that represents the name of the application. |
|
A string value that represents the path of the temporary file used to deploy the application. |
|
A Map<String, String> that represents the application properties. |
Implement Business Logic
In the following example, every application deployed in the Mule runtime must have an application property called business
. Its value represents the department owner of the application.
string applicationBusiness =
(applicationProperties == null)
? null
: applicationProperties.get("business");
if (applicationBusiness != null && applicationBusiness.equals(allowedBusiness)) {
LOGGER.info(welcomeMessage);
return;
}
throw new ArtifactValidationException(errorMessage);
Implement Custom Exceptions
Create a custom exception that represents the previous error.
In the package org.example
, add a new package called exceptions
and create the following class:
public class BusinessNotAllowedException extends ApplicationValidationException {
public BusinessNotAllowedException(String message) {
super(message);
}
}
The project directory layout shows the following:
./mule-agent-hello-validator/src/main/java/org/example/agent/exceptions
./mule-agent-hello-validator/src/main/java/org/example/agent/exceptions/BusinessNotAllowedException.java
Replace the generic ApplicationValidationException
to BusinessNotAllowedException
:
throw new BusinessNotAllowedException(errorMessage);
Add the Guice Configuration
-
Create the
BaseModuleProvider
class.In the package
org.example
, add a new package calledconfiguration.guice
and create the following class:public class MuleAgentHelloValidatorProvider extends BaseModuleProvider { @Override protected void configureModule(Binder binder) { bindNamedSingleton(binder, ApplicationValidator.class, MuleAgentHelloValidator.class); } }
-
Create the
BaseModuleProvider
class.In the directory
src/main
, add a new folder calledMETA-INF/services
and create the following file:Name:
com.mulesoft.agent.configuration.guice.ModuleProvider
Content:
com.example.configuration.guice.MuleAgentHelloValidatorProvider
The project directory layout shows the following:
./mule-agent-hello-validator/src/main/resources
./mule-agent-hello-validator/src/main/resources/META-INF
./mule-agent-hello-validator/src/main/resources/META-INF/services
./mule-agent-hello-validator/src/main/resources/META-INF/services/com.mulesoft.agent.configuration.guice.ModuleProvider
./mule-agent-hello-validator/src/main/java/org/example/agent/configuration
./mule-agent-hello-validator/src/main/java/org/example/agent/configuration/guice
./mule-agent-hello-validator/src/main/java/org/example/agent/configuration/guice/MuleAgentHelloValidatorProvider.java
Build the Application Validator
Run the following command:
mvn clean install
A JAR file is generated in the target directory:
./mule-agent-hello-validator/target
./mule-agent-hello-validator/target/mule-agent-hello-validator-1.0-SNAPSHOT.jar
Install the Application Validator
-
Place the JAR file in
$MULE_HOME/server-plugins/mule-agent-plugin/lib
. -
Access the
args
parameter keys and values and print them to the console:public void validate(Map<String, Object> args) throws ApplicationValidationException { // Values injected by the MuleAgentApplicationValidator service String applicationName = (String) args.get("_APPLICATION_NAME"); String applicationFilePath = (String) args.get("_APPLICATION_FILE_PATH"); Map<String, String> applicationProperties = (Map) args.get("_APPLICATION_PROPERTIES"); // Validator configuration values String business = (String) args.get("business"); String welcomeMessage = (String) args.get("welcomeMessage"); String errorMessage = (String) args.get("errorMessage"); LOGGER.info("Values injected by the service:"); LOGGER.info("\tApplication name: {}", applicationName); LOGGER.info("\tApplication file path: {}", applicationFilePath); LOGGER.info("\tApplication properties: {}", applicationProperties); LOGGER.info("Validator configurations:"); LOGGER.info("\tBusiness: {}", business); LOGGER.info("\tWelcome message: {}", welcomeMessage); LOGGER.info("\tError message: {}", errorMessage); }
Update the mule-agent.yml File
Add the validation configuration in the service:
services:
mule.agent.artifact.validator.service:
enabled: true
validators:
- type: helloValidator
name: defaultHelloValidator
enabled: true
args:
business: finance
welcomeMessage: 'Hi, welcome to Finance Cluster Runtimes'
errorMessage: 'I am sorry, you are not allowed to deploy in this Cluster'
Start Mule Runtime
Start Mule Runtime and verify that the validator configuration was successful. The console shows the following logs:
AgentArtifactValidatorService: Total validators loaded: 1
AgentArtifactValidatorService: Validators listed by type:
AgentArtifactValidatorService: Type: helloValidator Names: [defaultHelloValidator]
Deploy an Application
Once the validator is built and installed, the Agent Validator Service invokes the custom validator when you deploy an application:
Curl command:
curl -X PUT 'http://localhost:9999/mule/applications/app-01' \
-H 'Content-Type: application/json' \
-d '{
"url": "file:/tmp/app-01.jar",
"configuration": {
"mule.agent.application.properties.service": {
"applicationName": "app-01",
"properties": {
"business": "finance"
}
}
}
}'
Response:
{
"application": {
"name": "app-01"
},
"status": "Deployment attempt started"
}
Console logs:
MuleAgentHelloValidator: Values injected by the service:
MuleAgentHelloValidator: Application name: app-01
MuleAgentHelloValidator: Application file path: /tmp/mule-received-artifact-1793122713159733968/app-01.jar
MuleAgentHelloValidator: Application properties: {business=finance}
MuleAgentHelloValidator: Validator configurations:
MuleAgentHelloValidator: Allowed Business: finance
MuleAgentHelloValidator: Welcome message: Hi, welcome to Finance Cluster Runtimes
MuleAgentHelloValidator: Error message: I am sorry you not allowed to be deployed in this Cluster
MuleAgentHelloValidator: Hi, welcome to Finance Cluster Runtimes
Encrypt Values in the Validator Configuration
If the validator requires a secret provided in the mule-agent.yml
, you can use the amc_setup.sh
script to encrypt secrets, passwords, or any other value.
For more information, visit Encrypt Passwords.
-
Encrypt a single value
Set the
AGENT_VAR_master_password
environment variable to the main password:export AGENT_VAR_master_password=myPassword
-
Run the encryption utility:
$MULE_HOME/bin/amc_setup --encrypt my-secret-value
Output:
Mule Agent Installer ----------------------------- INFO: The encrypted value to paste on the mule-agent.yml file is: '![PBEWITHSHA1ANDDESEDE,wFE1D5V4DMb0uG77mzU+gibrlmnj3Kzb]'
-
Add the encrypted value in the validator configuration services:
mule.agent.artifact.validator.service:
enabled: true
validators:
- type: helloValidator
name: defaultHelloValidator
enabled: true
args:
business: finance
welcomeMessage: 'Hi, welcome to Finance Cluster Runtimes'
errorMessage: 'I am sorry you not allowed to be deployed in this Cluster'
secret: '![PBEWITHSHA1ANDDESEDE,wFE1D5V4DMb0uG77mzU+gibrlmnj3Kzb]'
Decrypt Values in the Validator
You can use the encryption service to decrypt values.
-
Inject the encryption service into your validator class:
@Inject EncryptionService encryptionService;
-
Decrypt the value:
String secret = (String) args.get("secret"); String secretPlainText = null; try { secretPlainText = encryptionService.decrypt(secret); } catch (AgentEncryptionException e) { LOGGER.error(e); } LOGGER.info("\tSecret: {}", secret); LOGGER.info("\tSecret (plain text): {}", secretPlainText);
Use case: Pass Encrypted Values to the Validator
Curl command:
curl -X PUT 'http://localhost:9999/mule/applications/app-01' \
-H 'Content-Type: application/json' \
-d '{
"url": "file:/tmp/app-01.jar",
"configuration": {
"mule.agent.application.properties.service": {
"applicationName": "app-01",
"properties": {
"business": "finance"
}
}
}
}'
Response:
{
"application": {
"name": "app-01"
},
"status": "Deployment attempt started"
}
Console logs:
AgentApplicationService: Deploying the app-01 application from URL file:/tmp/app-01.jar
MuleAgentHelloValidator: Values injected by the service:
MuleAgentHelloValidator: Application name: app-01
MuleAgentHelloValidator: Application file path: /tmp/mule-received-artifact-6683649864468336756/app-01.jar
MuleAgentHelloValidator: Application properties: {business=finance}
MuleAgentHelloValidator: Validator configurations:
MuleAgentHelloValidator: Allowed Business: finance
MuleAgentHelloValidator: Welcome message: Hi, welcome to Finance Cluster Runtimes
MuleAgentHelloValidator: Secret: ![PBEWITHSHA1ANDDESEDE,wFE1D5V4DMb0uG77mzU+gibrlmnj3Kzb]
MuleAgentHelloValidator: Secret (plain text): my-secret-value
MuleAgentHelloValidator: Hi, welcome to Finance Cluster Runtimes