[MessagingError message=''null' is not a valid destination.']

Categories: flex
Written By: sebi

Remoting again …
Ingredients: service-config.xml, RemoteObject, constants for conditional compile, flex_sdk_3.4.0.6955
Result: [MessagingError message=''null' is not a valid destination.']

I always try to find the easiest way to fit our projects to multiple environments with the less need of modifications in the source. The location of the remoting gateways is a typical variable. Specially when I have lots of environments, like dev, test, stage and live. And multiple RemoteObjects also.

Usually I don’t use the services-config.xml to configure the RemoteObjects, but right in this project I did. So I figured out, that I simply set up multiple channels in my services-config.xml, and I just simply swap the destination of the RemoteObjects to change the gateways.

The next step was obviously to extract this property to a variable, I decided to use the capability to assign constants for conditional compiling, with this I eliminated the variable from the actual source code, so every developer can has his own version of property files or project files which contains the url of his own dev server.

I set up everything:

<?xml version="1.0" encoding="UTF-8"?>
<!--
	$LastChangedRevision: 133 $
	$LastChangedBy: balazs $
	$LastChangedDate: 2009-12-08 16:48:46 +1300 (Tue, 08 Dec 2009) $
-->
<services-config>
    <services>
        <service id="amf-service"
            class="flex.messaging.services.RemotingService"
            messageTypes="flex.messaging.messages.RemotingMessage">
            <destination id="dev">
                <channels>
                    <channel ref="dev-endpoint"/>
                </channels>
                <properties>
                    <source>*</source>
                </properties>
            </destination>
            <destination id="test">
                <channels>
                    <channel ref="test-endpoint"/>
                </channels>
                <properties>
                    <source>*</source>
                </properties>
            </destination>
            <destination id="stage">
                <channels>
                    <channel ref="stage-endpoint"/>
                </channels>
                <properties>
                    <source>*</source>
                </properties>
            </destination>
            <destination id="live">
                <channels>
                    <channel ref="live-endpoint"/>
                </channels>
                <properties>
                    <source>*</source>
                </properties>
            </destination>
        </service>
    </services>
    <channels>
        <channel-definition 
        	id="dev-endpoint"
            class="mx.messaging.channels.AMFChannel">
            <endpoint 
            	uri="http://{server.name}:{server.port}/project/messagebroker"
                class="flex.messaging.endpoints.AMFEndpoint" />
        </channel-definition>
        <channel-definition 
        	id="test-endpoint"
            class="mx.messaging.channels.AMFChannel">
            <endpoint 
            	uri="http://{server.name}:{server.port}/projects/project/messagebroker"
                class="flex.messaging.endpoints.AMFEndpoint" />
        </channel-definition>
        <channel-definition 
        	id="stage-endpoint"
            class="mx.messaging.channels.AMFChannel">
            <endpoint 
            	uri="http://{server.name}:{server.port}/messagebroker"
                class="flex.messaging.endpoints.AMFEndpoint" />
        </channel-definition>
         <channel-definition 
        	id="live-endpoint"
            class="mx.messaging.channels.AMFChannel">
            <endpoint 
            	uri="http://{server.name}:{server.port}/messagebroker"
                class="flex.messaging.endpoints.AMFEndpoint" />
        </channel-definition>
    </channels>
</services-config>

In this example I don’t have really different urls, but in real they are far not the same. You can see I refer to 4 different environments. Each of them has a unique id, I use in the source code to access the endpoint. I extract exactly this property to an external place, in the simplest case to the project’s settings, but it can be an Ant build file, anything.

Store the RemoteObjects in a central place:

<?xml version="1.0" encoding="utf-8"?>
<!--
	$LastChangedRevision: 133 $
	$LastChangedBy: balazs $
	$LastChangedDate: 2009-12-08 16:48:46 +1300 (Tue, 08 Dec 2009) $
-->
<mx:Object
	xmlns:mx="http://www.adobe.com/2006/mxml">
 
	<mx:RemoteObject
		showBusyCursor="true"
		id="countriesService" 
		destination="{CONFIG::env}"
		source="CountriesController" />
 
	<mx:RemoteObject
		showBusyCursor="true"
		id="helpsService" 
		destination="{CONFIG::env}"
		source="HelpsController" />
 
	<mx:RemoteObject
		showBusyCursor="true"
		id="designsService" 
		destination="{CONFIG::env}"
		source="DesignsController" />
 
	<mx:RemoteObject
		showBusyCursor="true"
		id="patternsService" 
		destination="{CONFIG::env}"
		source="PatternsController" />
 
	<mx:RemoteObject
		showBusyCursor="true"
		id="shapesService" 
		destination="{CONFIG::env}"
		source="ShapesController" />
 
	<mx:Script>
		<![CDATA[
 
			import mx.logging.ILogger;
			import mx.logging.Log;
 
			public static var _instance:RemoteServices;
 
			private const LOG:ILogger = mx.logging.Log.getLogger( "com.sebesteny.examples.services.RemoteServices" );
 
			public static function getInstance():RemoteServices
			{
 
				if( !_instance )
				{
					_instance = new RemoteServices()
				}
				return _instance
			}
		]]>
	</mx:Script>
</mx:Object>

In this file I use a constant, a compile time constant as the destination for the RemoteObjects. Only the value of this endpoint will be compiled into my application.

And set up the compiler settings ( note the double quotes around the value of the property ):

-services services-config.xml -define CONFIG::env "'dev'"

But here came the surprise, since the Flash player presented a nice exception - with a bit mysterious message:

[MessagingError message=''null' is not a valid destination.']

Now that sounds stupid. I replaced the {CONFIG::env} with a static value, everything is fine. Replace with any variable, the error comes again. It is annoying. After examining the generated source code, I could see that the mxmlc resolves the code in a way that he first assigns a null value to the destination property, which raises the exception. No workaround with my prerequisites.

Luckily it wasn’t me the first, who ran into this issue, and he had filed a bug in the Adobe’s Jiira, here:
https://bugs.adobe.com/jira/browse/BLZ-340?rc=1

It is the BlazeDS’s space, but the problem is the same. And as the greatest surprise, that the bug has been actually fixed with a newer release of the sdk than i used.

So I updated the sdk to version flex_sdk_3.4.0.9271 ( the most current version right now, but the point to have a version greater than 7172 in SDK 3.x branch), and here we go, works like a charm. Great job.

Leave a Reply