Mule 3 Invocation Property Improvements
JIRA Issue |
|
|---|---|
Public Forum Thread |
http://forums.mulesoft.org/thread.jspa?threadID=7251&tstart=0 |
Motivation
Background:
Since Mule 2 message properties have been an area of Mule causing confusion and bugs. A significant of work went into improving one aspect of message properties in Mule 3.0:
1) Scopes were made more explicit. Instead of getProperty() scanning scopes, it uses a single default scope, any other scope needs to be defined explicitly, the same when setting properties.
2) Inbound scoped properties are no longer propagated via outbound endpoints of the same service/flow, instead properties need to be explicitly copied from inbound to outbound scope if you want to propagate them.
3)The VM transport now autoamtically copies outbound properties to inbound scope discarding original inbound endpoints.
Even with these improvements we have seen a number of issues with message properties in Mule 3.1 and 3.2. These problems primarily resolve around invocation and session properties. By their nature they have a scope that outlives a single message and need to be available throughout a whole flow (invocation) or multiple flows (session).
These remaining issues are a result of two things:
1) Flow is much more flexible than service ever was so there are so many more places/scenarios where these properties need to be propagated than before.
2) Invocation properties are stored as part of the message yet the scope of invocation properties is significantly broader than a single message.
Goals:
Without changing existing expected functionality:
- Ensure that invocation scope properties work as expected and this behavior is well documented
- Change were properties are stored to limit property copying/merging.
- Ensure that behavior is consistent.
- Ensure that behavior is fully tested.
- Limit the number of places MuleEvent is copied to limit property copying/merging.
Approach
The primary issue with invocation properties is that they are stored on the MuleMessage and not on the MuleEvent. In a flow the MuleMessage can be short-lived while the MuleEvent conceptually has the same scope as the flow (there are some places where a copy is needed). Invocation properties need to be available throughout a the flow and so by storing these on the MuleEvent property merging/copying can be avoided and things simplified.
1) Move invocation properties to MuleEvent
In order to do this a map of properties will be added to DefaultMuleEvent and get/setInvocationProperty() API added to MuleEvent (get/setPRoperty() won't be used to not conflict with old 2.x method names)
This map of properties will then be injected into the MuleMessage when the MuleEvent it created
Note: Once invocation properties have been moved up to MuleEvent it will be illegal to set invocation properties on a message before it is associated with an event and an IllegalStateException will be thrown.
Note: The MuleEvent/MuleMessage relationship isn't nice, but this is not easy to improve so will be maintained as is.
Migration Impact
The getInvocationProperty()/setInvocationProperty() methods in MuleMessage will be deprecated but will continue to be usable and will use the map of properties injected by the event to retrieve values.
Risk Mitigation
This change is risky, but given its very core, everything tests it. That said specific new tests will be created. Also acceptance criteria will be validated by QA.
2) Ensure MuleEvent properties are propagated throughout Flow
Moving invocation properties to MuleEvent is part an important part of the solution but not all of it. MuleEvent is copied in a large number of places so this needs to be considered. Either MuleEvent copying should conserve the same properties map instance (although there are places where a copy IS needed) or we need to significantly decrease MuleEvent copying such that it's only copied when needed (and properties are copied too).
The ideal approach here is that we reduce MuleEvent copying, this also has other benefits for code-cleanliness and to remove inconsistencies when using RequestContext.
- Make MuleEvent message mutable
- Remove all Event copying just to update message
- Review/reduce all other event copying
- Determine the places where invocation properties DO need to be copied.
- Cleanup RequestContext/OptimizedRequestContext (optional)
- Create builder for MuleEvent (optional)
- Tests!
Migration Impact
DefaultMuleEvent constructors may chance. And MuleEvent creation will change is a builder is introduced, no other migration impact though to API or config.
Risk Mitigation
This change is risky, but given its very core, everything tests it. That said specific new tests will be created. Also acceptance criteria will be validated by QA.
Review/Fix JIRA Issues
http://www.mulesoft.org/jira/browse/MULE-4769
http://www.mulesoft.org/jira/browse/MULE-5820
Documentation
Invocation Properties Documentation
Overal Migration Impact
The only potential migration impact is if there are people using the broken behavior such that when it's fixed they see properties they assumed weren't available in the current context.
The way around to is to:
1) Ensure Mule properties documentation is very clear about how the scopes work for 3.3
2) Call out in migration guise and/or release notes that properties now work correctly (i.e. are propagated everywhere they should be)
Overal Risks
There is a decent amount of internal refactoring required for these changes. The risk of regressions will be mitigated:
- Existing test cases have large amount of coverage of MuleMessage/MuleEvent creation and copying and some coverage of session/invocation scope properties.
- New unit tests will be created along with changed.
- Acceptance Criteria will be defined and tested by someone other than the developer.
Acceptance Criteria
Same Flows
Given:
- Invocation property p1 set in MP1
- Invocation property p2 set in MP2
Then: - Invocation property p1 is available in MP2
- Invocation property p1 is available in MP3
- Invocation property p2 is available in MP3
- Invocation property p2 is NOT available in MP1
Different Flows
Given:
- Invocation property p1 set in MP1
Then: - Invocation property p1 is available in MP2
- Invocation property p1 is NOT available in MP3
Flow-Ref -> Sub-Flow/Flow:
Given:
AND
- Invocation property p1 set in MP1
- Invocation property p2 set in MP2
Then: - Invocation property p1 is available in MP2
- Invocation property p1 is available in MP3
- Invocation property p2 is available in MP3
Outbound Endpoint in Flow
Given:
- Invocation property p1 set in MP1
- Invocation property p2 set in MP2
Then: - Invocation property p1 is available in MP2
- Invocation property p1 is available in MP3
- Invocation property p2 is available in MP3
NOTE: This needs to work with real transport e.g. http and not just VM.
Router in Flow
Given:
- Invocation property p1 set in MP1
- Invocation property p2 set in MP2
Then: - Invocation property p1 is available in MP2
- Invocation property p1 is available in MP3
- Invocation property p1 is available in MP4
- Invocation property p2 is available in MP3
- Invocation property p2 is available in MP4
Wire-Tap/Async/Enricher
Given:
AND
AND
- Invocation property p1 set in MP1
- Invocation property p2 set in MP2
Then: - Invocation property p1 is available in MP2
- Invocation property p1 is available in MP3
- Invocation property p2 is NOT available in MP3
Splitter/Aggregator in Flow
Given:
- Invocation property p1 set in MP1
- Invocation property p2 set in MP2
- Invocation property p3 set in MP3
Then: - Invocation property p1 is available in MP2
- Invocation property p1 is available in MP3
- Invocation property p1 is available in MP4
- Invocation property p2 is available in MP3
- Invocation property p2 is available in MP4
- Invocation property p3 is available in MP3
- Invocation property p3 is available in MP4
Documentation
Documentation for properties needs to be significantly improved.