This is part 2 of a series on changes to the Mule Message in Mule 4 Beta, read part 1!
The Mule 4 Beta release has significant internal improvements to Mule runtime. In the last post, we talked about immutability and collections with Mule Messages. In this post, I will go into detail on inbound and outbound properties in Mule Messages, as well as variables and other changes.
Message properties are just as important as Message payload. They are used to convey metadata about the payload from a source such as a file’s name and size, or in order to send a property such as a JMS CorrelationID when sending a message. In Mule 3, there were a number of usability issues that we repeatedly heard whenever we asked for user feedback.
In order to explain these changes in the simplest way possible, I’ll take the concrete example of an HTTP Proxy and explain the changes to both inbound and outbound properties independently.
In Mule 3, the HTTP listener populated inbound message properties with both the actual HTTP headers sent over the wire and ‘synthetic’ properties prefixed with ‘http.‘ These ‘synthetic’ properties consisted of properties not present in the set of incoming HTTP headers. Instead, ‘synthetic’ properties were populated by the connector itself. In the case of HTTP, these included properties such as the HTTP query parameters and the client IP address.
The issues that users encountered with this approach were born from the fact that there were two fundamentally different property types mixed in the same map. This made it harder to work with Message properties.
So if you needed to proxy the original HTTP headers, the only way to differentiate them from the ‘synthetic’ properties was via the absence of the ‘http.’ prefix, which is neither ideal nor reliable. Also, the set of ‘synthetic’ properties for a given transport or connector was not defined using a specific Java type, and this made it hard to discover and use.
In Mule 4 beta, inbound properties no longer exist. Instead, a Message is now made up of a Payload and Attributes, as shown below:
The new Attributes object replaces the inbound property scope. It allows for easy differentiation of incoming HTTP headers and other metadata about the request provided by the HTTP Listener. Also, as it is strongly typed, it is easy to discover and use the connector-populated metadata associated with each request, especially when combined with DataSense support in Anypoint Studio.
When a Flow is triggered (e.g. a new HTTP request is received) the connector, in this case, the HTTP Listener, will create a Message that composes both the HTTP body and an instance of HttpAttributes. The HttpAttributes instance will contain both the incoming HTTP headers and all other metadata. Because it is typed, it is easier to use and self-discover.
In Anypoint Studio and flow designer, and via DataSense, the attributes populated by the previous connector source or operation can be seen and used.The screenshot below depicts this in the context of the DataWeave Transform component. While this example is HTTP-centric, when a different source connector (e.g. JMS) is used, the attributes object will be a specific instance to the connector and will, in turn, provide access to connector-specific metadata, (e.g JMS correlation ID)
In Mule 3, you could add outbound message properties anywhere in your Flow. The next outbound endpoint or connector operation (e.g. an HTTP Requester) would then use the set of outbound properties present at that point in the Flow and send them, along with the current payload, via the outbound endpoint or connector (e.g. HTTP).
While this approach seems very convenient, it resulted in a lot of issues where the behavior of Flows and the outbound properties were not deterministic. Subsequently, the refactoring of a Flow or the introduction of a new connector operation in an existing Flow would significantly change the behavior of a Flow.
In Mule 4 beta, outbound properties no longer exist. Instead, the headers or properties (e.g. HTTP headers or JMS properties) that you wish to send as part of a request or message (e.g. HTTP request or JMS message) respectively are now configured explicitly as part of the connector operation configuration. This avoids the issues with outbound properties in Mule 3. If you do need to define the value of the header earlier in your Flow, you can still use a variable to store this value and use it later.
Impact on Application Design
The changes to Message properties will result in more deterministic flows. For Mule 3 users, the changes to Message properties will require a slight recalibration as to how users think about defining their integrations.
Note: If migrating existing applications to Mule 4 and you continue to use Mule 3 transports via the compatibility module, then Message properties will continue to work as they do in Mule 3. It is only when using the new connectors in Mule 4 that you will need to work with the new Attributes objects.
Flow variables remain largely untouched. We have renamed them to simply variables. Other than that, functionally nothing has changed in this regard since Mule 3.
We have removed session variables for a couple of reasons. Firstly, session variables that were propagated between different Flows didn’t have anything to do with a stateful client session. Secondly, session variables were often seen as security concern because variables defined in a Flow were automatically being propagated via HTTP headers or JMS properties. Consequently, users were frequently disabling this functionality.
The more security conscious, and explicit, way of propagating values between different flows or systems is via the explicit use of HTTP headers or JMS properties.
Impact on Application Design
Other than the changes required in migrating to DataWeave expressions, there is nothing specific to take into account regarding variables. If you are migrating an application from Mule 3 that uses session variables, it is quite likely that you didn’t ever need session variables, and flow variables will be sufficient. But, if you do need to propagate values between flows, then you should use set outbound and header/property as required in the source flow and then read this value from the attributes object in the destination flow.
The other changes we made to the Message structure were more internal and primarily concerned with improving the cohesiveness of the structure. This involved redefining the role of the Event and Message somewhat and introducing the concept of an EventContext to replace MuleSession.
The simplified updated model for those interested can be seen in the class diagram below.
- Message: The user message includes the payload, and an optional attributes instance. This is what users primarily work with and is what connector operations receive and return.
- Event (internal): The message, variables, authentication and group correlation (which contains the sequence number and group size). This is internal to the runtime and updated during flow execution as the message and variables are mutated. The Event also has a reference to the current EventContext.
- EventContext (Internal): Represents a single request or transaction with its correlationID and other details. The same EventContext instance is used throughout Flow execution.
I hope this blog has served to both provide some context and motivation around the changes to the Message structure in Mule 4 beta, but also given you some practical advice in terms of how to understand how you should think about designing Mule 4 beta applications by taking these changes into account.
Try Mule 4 Beta and Explore these Resources!
- Download Mule 4 and Studio 7 Beta
- Watch a Demo-driven Webinar on Mule 4 and Studio 7 Beta
- Read about Automatic Streaming in Mule 4 Beta
- Explore Other Topics on Mule 4 Beta