Mule Enum in Flow – issue with enum of same name as variable
When creating a flow in Mule recently, I hit an issue that kept me scratching my head for a number of hours, so thought I’d share it…
<?xml version="1.0" encoding="UTF-8"?>
<mule xmlns:http="http://www.mulesoft.org/schema/mule/http" xmlns:servlet="http://www.mulesoft.org/schema/mule/servlet" xmlns:vm="http://www.mulesoft.org/schema/mule/vm" xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation"
xmlns:spring="http://www.springframework.org/schema/beans" version="CE-3.5.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-current.xsd
http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/vm http://www.mulesoft.org/schema/mule/vm/current/mule-vm.xsd
http://www.mulesoft.org/schema/mule/servlet http://www.mulesoft.org/schema/mule/servlet/current/mule-servlet.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd">
<flow name="input-data" doc:name="input-data">
<composite-source doc:name="Composite Source">
<vm:inbound-endpoint exchange-pattern="one-way" path="pvoutput-data" doc:name="vm-pvoutput-data"/>
<servlet:inbound-endpoint path="/pvoutput-data" responseTimeout="10000" doc:name="servlet-pvoutput-data"/>
</composite-source>
<set-variable variableName="Received" value="#[new java.util.GregorianCalendar()]" doc:name="Received Date Time"/>
<set-variable variableName="DataSource" value="#[DataSource.valueOf(message.inboundProperties['X-Data-Source'])]" doc:name="Source"/>
<http:body-to-parameter-map-transformer doc:name="Body to Parameter Map"/>
<logger message="#[message]" level="DEBUG" doc:name="Logger"/>
<logger message="Received #[DataSource] Data: #[payload]" level="INFO" doc:name="Logger"/>
<choice doc:name="Source Choice">
<when expression="#[DataSource == DataSource.HOT_WATER]">
<expression-transformer doc:name="Hot Water" expression="#[new HotWaterData(Received, payload);]" />
</when>
<when expression="#[DataSource == DataSource.WEATHER]">
<expression-transformer doc:name="Weather" expression="#[new WeatherData(Received, payload);]" />
</when>
<when expression="#[DataSource == DataSource.INVERTER]">
<expression-transformer doc:name="Inverter" expression="#[new GenerationData(Received, payload);]" />
</when>
<when expression="#[DataSource == DataSource.METER]">
<expression-transformer doc:name="Meter" expression="#[new MeterData(Received, payload);]" />
</when>
<otherwise>
<logger message="Unexpected Data Source Type: #[DataSource]" level="ERROR" doc:name="Logger"/>
</otherwise>
</choice>
<vm:outbound-endpoint exchange-pattern="one-way" doc:name="combine-data" path="combine-data"/>
</flow>
</mule>
(or in pictorial format)
I’ve created a simple flow which receives a request on a servlet endpoint and then adds a variable depending on the source. The variable is named “DataSource”, but I also have an enum named DataSource which contains the following values:
package uk.co.vsf.aggregator.domain;
public enum DataSource {
HOT_WATER,
WEATHER,
INVERTER,
METER
;
}
There’s also a Mule configuration block which has imports to a number of classes including the DataSource enum.
<configuration doc:name="Configuration">
<expression-language autoResolveVariables="true">
<import class="uk.co.vsf.aggregator.domain.DataSource"/>
<import class="uk.co.vsf.aggregator.domain.HotWaterData"/>
<import class="uk.co.vsf.aggregator.domain.WeatherData"/>
<import class="uk.co.vsf.aggregator.domain.GenerationData"/>
<import class="uk.co.vsf.aggregator.domain.MeterData"/>
<import class="uk.co.vsf.aggregator.pvoutput.domain.AddStatusRequest"/>
<import class="uk.co.vsf.aggregator.CalendarUtils"/>
<import class="java.util.Calendar"/>
<import class="java.util.GregorianCalendar"/>
</expression-language>
</configuration>
I’ve then written a simple test which calls the composite input vm with a set of values and a data source of Hot_Water. You’ll notice from the flow that after determining the data source, it logs out the message, so we can see the stored variable:
Message properties:
INVOCATION scoped properties:
DataSource=HOT_WATER
...
All ok at the moment…
Just below that log statement is another which prints out the DataSource, but this time we get:
Received class uk.co.vsf.aggregator.domain.DataSource Data: {t=40.56, i=10}
Not what I’d expected!
And after that log statement the data source is used to determine the route of the message being processed. I expect it to get transformed into a HotWaterData object, but instead the message goes to the else statement:
Unexpected Data Source Type: class uk.co.vsf.aggregator.domain.DataSource
Well… after much head scratching… it was as simple as renaming the variable to something other than the same name as the enum value! (DOH)
Now I get the results I’d expected:
Received HOT_WATER Data: {t=40.56, i=10}
And the returned object is an instance of HotWaterData.
Hope this helps someone else!
Please enable the Disqus feature in order to add comments