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)
aggregator

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!