---
schema_version: "1"
id: 80896c532548e59bc43355fafea5e26f02a9eaa743047b4b3a2c5ac902bda84b
title: General Coding Rules
collection: mulesoft
version: current
locale: en-us
portal_url: https://docs.salesforce.com/mulesoft/current/en-us/mule-sdk/latest/general-coding-rules.md
canonical_url: https://docs.mulesoft.com/mule-sdk/latest/general-coding-rules
source_site: docs.mulesoft.com
content_type: documentation
content_hash: 885a4c9beccad7d1234f1cf9095a541864b8a01ebef49f7fbff68e803103b470
description: MuleSoft Documentation Site
release: "1.13"
latest: true
---
---
product: Mule SDK
version: 1.13
is-latest-version: true
---

# General Coding Rules

> For the full documentation index, see: https://docs.mulesoft.com/llms.txt

This set of general rules applies to any component of a module or connector. These apply on all
operations, sources, configs, connection providers, and functions).

## Connectors Must Closely Reflect the Target System

In the context of Anypoint Platform, a connector’s purpose is to bring the target system into the
Mule language. The connector **must not** add higher-level abstractions or include operations that
implement specific business use cases.

For example, imagine a billing API that contains resources for creating an invoice, adding items to
an invoice, and submitting an invoice. The connector for such an API **must** contain one operation
per each of those resources, but **must not** include an operation that combines all three calls
into a single unit.

The one exception is auto-paging operations, which, to achieve the paging effect, perform several
calls as part of processing the output of one single Mule operation.

## Do Not Mix Protocols

One connector **must** connect to only one type of protocol at a time. For example, suppose an
external system exposes a REST API, a SOAP API, and an OData API.

In Anypoint Platform, there are three different APIs, even if they access the same external system.
Therefore, each of those APIs **must** have its own connector, instead of one that understands the
three protocols.

## Exported Module Java API

Before reading this section, see [Classloading isolation](https://docs.mulesoft.com/mule-sdk/latest/isolation) in the Mule SDK.

The module **must** export only packages defined in your module. Packages from dependency libraries
**must not** be exported.

### Java Packages

Packages from the JDK are treated differently since modules don’t export them but only consume them.
Mule automatically exports all available Java packages for the modules to use.

However, the module **must** use only Java packages available on all of the JDKs supported by the
Mule versions that the module is compatible with. Vendor-specific packages such as com.sun **must
not** be used.

### Java Compatibility

See [Java Support](https://docs.mulesoft.com/general/java-support) to decide which Java version to use based on the
target Mule runtime.

#### Java 11 Compatibility

Starting with Mule 4.2.0, JDK 11 is also supported. That means that when depending on native Java
APIs, the module **must** account for the fact that the needed API might not be available given
Java’s new modular architecture (also known as
[Project Jigsaw](https://openjdk.org/projects/jigsaw/), first introduced in Java 9).

For example, if your module requires the Java Transaction API (JTA), the module **must** declare the
following dependency in its pom.xml file:

```xml
<dependency>
  <groupId>javax.transaction</groupId>
  <artifactId>javax.transaction-api</artifactId>
  <version>1.2</version>
</dependency>
```

Or if the Java Mail API is used:

```xml
<dependency>
  <groupId>javax.mail</groupId>
  <artifactId>javax.mail-api</artifactId>
  <version>1.6.2</version>
</dependency>
```

### Design for Thread Safety

Mule is a reactive execution engine, designed for highly concurrent workloads. Therefore, all
components **must** always be designed to support concurrent executions at minimal contention.

[Thread safety](https://en.wikipedia.org/wiki/Thread_safety) is a basic concept for any Java
developer familiar with concurrency. Users of the SDK are expected to be familiar with this.

## Use Immutable Payload and Attributes Objects

All output types, used as either payload or message attributes, **must** be immutable objects.

## Correct Use of Content Parameters

Make correct use of @Content parameters according to the MuleSoft
[Content Parameters](https://docs.mulesoft.com/mule-sdk/latest/content-parameters) document.

## Never Access Flow Variables

In Mule 4, variables are for exclusive access of end users only. No module **should** ever access
flow variables directly.

Although the SDK doesn’t provide any API for accessing them, optional parameters can be leveraged to
hack this restriction. For example:

```java
@Optional(defaultValue = "#[vars.foo]") String foo

@Optional(defaultValue = "#[vars]") Map<String, TypedValue<Object>> vars
```

However, these statements (or any other way of getting to the vars from inside a module) are
forbidden. Every piece of information required by the module **should** be made explicit through a
parameter. End users decide to assign that value to a variable or not.

Notice that violating this rule automatically violates position independence.

## Never Use Message Attributes as Parameters

No component **should** define a parameter of a type that’s also used as message attributes, even if
the attributes object is defined as part of the same module.

For example, if a connector has an operation that uses the LocalFileAttributes class as output
attributes, the following is illegal:

```java
public void checkAccess(@Content LocalFileAttributes attributes) {
        doCheckAccess(attributes);
}
```

Instead, add parameters that reflect what information from the attributes class you actually need:

```java
public void checkAccess(String path) {
 ...
}
```

## Use Correct Encodings

When connecting to systems that accept multiple encodings, the encoding to be used **must** be
configurable through a [Configuration Override](https://docs.mulesoft.com/mule-sdk/latest/config-override). This means that the encoding to
use **should** be parameterizable at the config level, but also on each component that requires it
(operations, sources, functions, and so on).

At the config level, the encoding parameter **must** default to the Mule default encoding, which is
obtained through the @DefaultEncoding annotation.

For example:

```java
public class MyConfig implements Initialisable {

        @DefaultEncoding
        private String defaultEncoding;

        @Parameter
        @Optional
        private String encoding;

        public void initialise() throws InitialisationException {
                if (encoding == null) {
                        encoding = defaultEncoding;
                }
        }

        public String getEncoding() {
                return encoding;
        }

}
```

## Duration Parameters

Modules often require that you configure durations with classical examples such as timeouts and
cache evictions.

Durations **must** be expressed as the combination of two parameters:

- An int or Integer scalar parameter with the Timeout suffix

- A java.util.concurrent.TimeUnit parameter that qualifies the scalar

  This parameter **must** be named exactly the same as its companion scalar except for adding the
  TimeUnit suffix. The TimeUnit parameter **should** default to SECONDS.

For example:

```java
/**
* The socket connection timeout value. This attribute works in tandem with {@link #connectionTimeoutUnit}.
*/
@Parameter
@Optional(defaultValue = "5")
@Placement(tab = ADVANCED_TAB, order = 1)
@Summary("Socket connection timeout value")
private int connectionTimeout;

/**
* A {@link TimeUnit} that qualifies the {@link #connectionTimeout}
*/

@Parameter
@Optional(defaultValue = "SECONDS")
@Placement(tab = ADVANCED_TAB, order = 2)
@Summary("Time unit to be used in the Timeout configurations")
private TimeUnit connectionTimeoutUnit;
```

## Timeouts Must Have Configurable Configuration Overrides

All components that perform operations that could be affected by timeouts **must** make those
configurable through [Configuration Override](https://docs.mulesoft.com/mule-sdk/latest/config-override) parameters.

Such timeouts **must** be expressed as duration parameters.

## Only Primary @Content Should Default to Payload

No parameter other than a primary content **should** default to payload. This means that the
following **should** never be used:

```java
@Optional(defaultValue = "#[payload]")
```

## Handle Dates and Time Parameters

Date and time parameters **must** be implemented by using java.time.LocalDate,
java.time.LocalDateTime, or java.time.ZonedDateTime types. Do not use java.util.Date or
java.util.Calendar.

## Check the End-to-End Experience

Before publishing your module, test it in Anypoint Studio. Make sure it provides good usability and
a good experience. A module that works but is hard to use is not complete.

You **must** check for the following:

- DataSense is correctly resolved for all input parameters and output values.

- Each component’s parameter [layout](https://docs.mulesoft.com/mule-sdk/latest/parameter-layout) is correct.

- No typos exist in labels and descriptions.

- Users can easily build an application that uses the module’s main use cases.

## Discourage the Use of POJOs

The SDK allows using POJOs as both input parameters and output types. However, their use is
discouraged. All modules **should** make a best effort to use JSON or XML instead. In the case of
dynamic types, Java Maps may also be used.

This rule doesn’t mean that there’s no use case for using POJOs, nor that you need to convert all
structures to JSON or Java Maps. This rule is merely about favoring data formats that interoperate
better with other components and avoid serialization issues.

For example, suppose that your organization developed a Java taxes library that you want to leverage
in your Mule applications. If this library returns POJOs, it is okay for you to build an SDK module
that wraps this library, even if that means that this tax module will accept and produce POJOs.

Instead, if what you are leveraging is a Tax API that returns JSON, then your Tax connector
**should** return the same JSON as the API instead of transforming that JSON into a POJO.

## Expose POJOs

All POJOs that are exposed (because they’re being used as output types, input parameters, or message
attributes) **must** be DataWeave compliant. This means that all have a default constructor and a
getter method for each @Parameter annotated field.

## User Must Not Be Aware of Java Types

The user **must not** need to know the Java type used to implement a module in order to use it.

For example, consider the following transformation:

```json
{
  name: "Pedro",
  address: {
           x: 11,
         y: 12
  }
}  as com.foo.Person
```

The module **must** be defined in a way in which explicit transformations such as this are not
needed. Some ways of achieving this are:

- Don’t use POJOs to represent a person (recommended)

- Make com.foo.Person a DataWeave compliant concrete class

- When used as an input parameter, refer to com.foo.Person explicitly instead of using an abstract
  type or interface

## Payload and Attributes Must Be Serializable

Message attributes objects returned by either operations or message sources **must** be Java
Serializable. Otherwise they cannot be used with ObjectStore, VM queues, or Mule in cluster mode.

## Don’t Access the MuleContext

The MuleContext is deprecated and **must not** be accessed by any module or connector.

Most of the time, the only reason for a module to access the MuleContext is to obtain certain
Runtime service. For example:

```java
muleContext.getRegistry().lookupByType(ObjectStoreManager.class)
```

Instead, use @Inject to obtain those services.

```java
public class MyComponent {

@Inject
ObjectStoreManager osm;
}
```

## Log Through SLF4J

All logging **must** be made through the SLF4J API.

The module **must not** add any dependency with this API as it’s already provided in the parent pom
file provided by MuleSoft.

## All Loggers Must Be Static

Loggers are expensive to create. Therefore, all loggers **must** be private, static, and final.

For example:

```java
public class Operation {

        private static final Logger LOGGER = LoggerFactory.getLogger(Operation.class);

        ...

}
```

## Avoid Static State

All module classes **must not** contain a static state. The only exceptions are Loggers and the
serialVersionUID of Serializable classes.

## Choose the SDK Version

Normally, developers tend to use the latest available version of any given product. This **should
not** be the case with the SDK. To extend Mule, you should:

- Identify the features you need

- Choose the lower version that includes the features you need.

For more on selecting the correct SDK version, see [Choosing the SDK Version](https://docs.mulesoft.com/mule-sdk/latest/choosing-version).

## Do Not Use Boxed Booleans

Boolean parameters **must** be of the native boolean type. A boxed Boolean is not allowed as a
parameter type.

All boolean parameters are considered optional and **must** default to false. You can use the
@Optional annotation to change the default of a boolean, but you can never make it a required
parameter.

## Use Plural Names for List Parameters

All parameters implemented as a Java Collection, Map, or Array, or any other type that represents an
array of some sort, such as a JSON array, **must** have a plural name.

## Use Semver Versioning

Modules **must** be versioned using the [Semantic Versioning](https://semver.org/) standard.

## Use Strict Camel Casing

The entirety of the module’s source code **must** correctly apply camel casing. This is critical
since otherwise the SDK will not be able to correctly generate the XML DSL or process layouts.

## Specify Java Compatibility

Specify the Java compatibility of your custom module. In Mule 4.6.0 and later, custom modules that
do not specify the Java compatibility are assumed to be compatible with Java 8 and Java 11 only. If
your custom module is compatible with a more recent Java version, you must specify the Java
compatibility to include that version.

For more information, refer to [Java Version Support](https://docs.mulesoft.com/mule-sdk/latest/java-version-support).

## See Also

- [Salesforce Help](https://help.salesforce.com)

- [Mule SDK Development Best Practices](https://docs.mulesoft.com/mule-sdk/latest/best-practices)
