A typical source of confusion when developers start working with RemoteObject or other BlazeDS/LCDS related classes is where and most importantly *when* the configuration of your services is being read.
The question often arises after an application stops working when you move it to another server. This is one of the most frequently asked questions related to BlazeDS and LCDS, so I figured I would answer it here. There is nothing really new in this post, but hopefully this will be a good point of reference.
When you create a new BlazeDS or LCDS project in Flex Builder, you are typically told to select J2EE as the “Application Server Type” and then check “use remote object access service”. This adds a compiler argument pointing to the location of your services-config.xml. If you check the Flex Compiler properties of your Flex Builder project, you’ll see something like this:
-services “c:\blazeds\tomcat\webapps\samples\WEB-INF\flex\services-config.xml”
When you then compile your application, the required values of services-config.xml are baked into the SWF. In other words, services-config.xml is read at compile time and not at runtime as you may have thought intuitively. To abstract things a little bit, you can use tokens such as {server.name}, {server.port}, and {context.root} in services-config.xml. However, {context.root} is still substituted at compile time, while {server.name} and {server.port} are replaced at runtime using the server name and port number of the server the SWF was loaded from (which is why you can’t use these tokens for AIR applications).
Fortunately, the Flex SDK provides an API that allows you to configure your channels at runtime and entirely externalize your services configuration from your code (you definitely don’t want to recompile your application when you move it to another server). At a high level, it works like this:
var channelSet:ChannelSet = new ChannelSet();
var channel:AMFChannel = new AMFChannel("my-amf", "http://localhost:8400/lcds-samples/messagebroker/amf");
channelSet.addChannel(channel);
remoteObject.channelSet = channelSet;
This is still not what we want because the endpoint URL is still hardcoded in the application. At least in this case it’s obvious that it is. So, the last step is to pass that endpoint URL value at runtime. There are a number of ways you can pass values to a SWF at runtime (flashvars, page parameters, etc). The approach I usually use is to read a configuration file using HTTPService at application startup. That configuration file includes (among other things) the information I need to programmatically create my channel set at runtime. Here is a basic implementation:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
applicationComplete="configSrv.send()">
<mx:Script>
<![CDATA[
import mx.controls.Alert;
import mx.messaging.channels.AMFChannel;
import mx.messaging.ChannelSet;
import mx.rpc.events.ResultEvent;
private var channelSet:ChannelSet;
private function configResultHandler(event:ResultEvent):void
{
var xml:XML = event.result as XML;
var amfEndpoint:String = "" + xml..channel.(@id=="amf").@endpoint;
if (amfEndpoint == "")
{
Alert.show("amf channel not configured", "Error");
}
else
{
channelSet = new ChannelSet();
var channel:AMFChannel = new AMFChannel("my-amf", amfEndpoint);
channelSet.addChannel(channel);
ro.channelSet = channelSet;
ro.getProducts();
}
}
]]>
</mx:Script>
<mx:HTTPService id="configSrv" url="config.xml" resultFormat="e4x" result="configResultHandler(event)"/>
<mx:RemoteObject id="ro" destination="product"/>
<mx:DataGrid dataProvider="{ro.getProducts.lastResult}" width="100%" height="100%"/>
</mx:Application>
The configuration file looks like this:
<?xml version="1.0" encoding="utf-8"?> <config> <channels> <channel id="amf" endpoint="http://localhost:8400/lcds-samples/messagebroker/amf"/> </channels> </config>
NOTE: With that type of runtime configuration in place, you can create plain Flex Builder projects (you can select None as the application server type).
This particular example is not extremely flexible. It assumes I will always work with an AMF channel and therefore the only thing my application needs to know at runtime is the AMF channel endpoint URL. For RemoteObject that’s a fairly safe bet, however for messaging-related classes (Producer and Consumer), you may also want to externalize the type of channel you use (AMF Polling, long polling, streaming, RTMP, etc.). Before you start creating that kind of dynamic configuration system, you may want to take a look at the Flex ActionScript framework that does that very well.

22 Comments
thank you christophe – very helpful! SB
We actually had the requirement to read these parameters(ie http://uniqueserver:8080) via flash vars, then construct the secure amf channel.
Just to note that the Swiz framework includes very nice support for dynamic ChannelSet creation.
Hi Brian,
I looked at Swiz and I like it as I hope you can tell from the blog post. You guys are doing a really great job. On this particular topic of externalizing service configuration, I didn’t see a built-in solution to externalize the configuration from the source code (I may have missed it as I only had a limited amount of time to explore the framework). In this example, the port and context root are still hard coded.
Also, at first glance, I didn’t see the real benefit of using DynamicChannelSet compared to the standard ChannelSet class. For example, in my Beans.xml I can replace:
<DynamicChannelSet id="myAmfChannel">
<serverPort>8400</serverPort>
<contextRoot>/lcds-samples</contextRoot>
</DynamicChannelSet>
<mx:RemoteObject id="contactService" destination="contacts" channelSet="{myAmfChannel}"
with
<mx:ChannelSet id="channelSet">
<mx:AMFChannel id="amf" url="http://localhost:8400/lcds-samples/messagebroker/amf"/>
</mx:ChannelSet>
<mx:RemoteObject id="contactService" destination="contacts" channelSet="{channelSet}"/>
The second approach uses the SDK classes and doesn’t have a dependency on services-config.xml either. Are there additional benefits in using DynamicChannelSet?
Thanks,
Christophe
Hi Christophe
We are developing a flex chart componment like Yahoo finance. but when we connected it with live datafeed, we experience serious lagging probelm. It got worse when we add technical indicators to it. We have asked for suggestions from Adobe HK. They recommend us to reduce the frequency of datafeed var numNull:int = Math.floor( (1000/9) /(1000/24)) / 2; to avoid accumulation of refresh events. But performance is prime to us and we need to use realtime data. Could you give us some suggestions on how to handle this problem. We are so impressed with your traderdesktop. It would be grateful if you could you give us an email so that we could show you our development? Thanks.
Christophe,
I always enjoy reading your posts. I recently had that same problem since I was trying to install BlazeDS on a remote server and every single tutorial on the internet I found was about installing it and running it locally. I made a post that had to do with that on my blog althought you explained it a lot better than I did. Check it out if you’d like: BlazeDS & WSDL Introspection.
Hi Christophe,
If we remove services-config.xml from compiler arguments we get “MessagingError message=’Destination ‘Destination_name’ either does not exist or the destination has no channels defined (and the application does not define any default channels.”
As stated in LCDS AMF serialization documentation, the read-only properties of a java bean are ignored in the AMF serialization process. What do I need to do so that the read only properties are also serialized?
Any link or documentation would be helpful
If you externalize your services, don’t forget to make the Server available to the clients placing the crossdomain.xml file in the root server.
Hi Christophe, nice post :)
Could you give me some tips about my issues?
I have a main java web application that needs to send messages (jms) to my flex dashboard application. Both applications are in the same server but my blazeDS is running in other server under tomcat.
How could I config both applications to produce and consume messages using the remote blazeDS ?
Some people told me to use JNDI but I don´t know how very well that API.
Thanks
thank you admin good fluser
I cannot believe this will work!
I would like have a linux server running as our continuous integration.
We build locally using Flexbuilder on windows, but we cant get linux to compile any services. Any ideas???
Hi Christophe,
I am developing an application using LCDS and J2EE.
What are the steps required to build an application.
What all do we need?
Hi Christophe,
I have developed an application using Flex , LCDS and J2EE. The application works very well when deployed in my local system. When I deploy the application in another system, i see that the LCDS call are not happening. What might the resolution for this issue?
Thank You
Awesome code Sir, I guess I can delete the following code from my service-config.xml
<endpoint uri="//secret
since I define the stuff in my extra service file on my server?
thanks for any tips
program yükle Good admin than you
Use it with a lot of caution!!!!
It seems to work, but the code really doesn’t works when you open several channels at the same time. You will get a lot of “Channel disconnected” exceptions.
I think the ideas exposed here are very very useful and very they are well explained. Thanks a lot. Though users could have problems if they use your code without any correction.
Pablo.
Hi again!
Problem solved! Define and initialize an unique static ChannelSet and apply it to all created remote objects.
I guess ChannelSet (or AMFChannel) is a limited System resource. So you can’t open a lot of channels simultaneously. But you can reuse the same channel for all remote objects.
That is based on my experience. I can’t justify that.
Thanks a lot Christopher!
Hi Cristophe,
are you aware that you can use relative URL’s for the endpoints, too? The URL is resolved relative to the url where the Flex file was loaded from. This solves the “my flex file moved to another server” problem, without any extra complexity.
Of course, this only works if the file is access from the server.
Regards,
Allard
I am trying Flex client configuration for BlazeDS in SunOneWebserver.
I am getting error like this:
faultcode=”Client.Error.MessageSend”
faultDetail=”Channel.Connect.Failed error NetConnection.Call.Failed.
Hi Vineet,
I could compile and execute this sample code without specifying -service option to mxmlc (sdk version 3.5).
But yes, BlaseDS throws runtime exceptions while initializing MessageBrokerServlet if I start it
without services-config.xml in WEB-INF/flex
Exception: flex.messaging.config.ConfigurationException: Please specify a valid ‘services.configuration.file’ in web.xml.
You specified ‘/WEB-INF/flex/services-config.xml’. This is not a valid file system path reachable
via the app server and is also not a path to a resource in your J2EE application archive.
or
removing the element from services-config.xml [as suggested by Nikos Katsikanis"]
Exception: flex.messaging.config.ConfigurationException: Attribute ‘endpoint’ must be specified for element ‘channel-definition’.
or
not having a channel-definition in services-config.xml that is referred by any element in remoting-config.xml.
Exception: flex.messaging.config.ConfigurationException: channel not found for reference ‘my-amf’.
I could simulate the kind of client side error what you get i.e.
[RPC Fault faultString="[MessagingError message='Destination 'echoServiceDestination' either does not exist or the destination has no channels defined (and the application does not define any default channels.)']” faultCode=”InvokeFailed” faultDetail=”Couldn’t establish a connection to ‘echoServiceDestination’”]
by removing applicationComplete=”configSrv.send()” from the main application tag.
But the NetConnection client side error i.e.
[RPC Fault faultString="Send failed" faultCode="Client.Error.MessageSend" faultDetail="Channel.Connect.Failed error NetConnection.Call.Failed: HTTP: Status 500: url: 'http://localhost:8090/blazeds/messagebroker/amf'"]
occurs in all other cases viz when there is run time exception when initializing MessageBrokerServlet or wrong endpointurl (say port as 8090 instead of 8080) specified in config.xml as might be the case with Shanthi.
6 Trackbacks
[...] Externalizing Service Configuration using BlazeDS… (from Christophe Coenraets) [...]
[...] had recently read Christophe Coenraets blog post title, “Externalizing Service Configuration using BlazeDS and LCDS” which addresses the same issue with configuring Flex applications to use BlazeDS or [...]
[...] documentation to figure something out but Christophe Coenraets came to the rescue with a post on externalizing your service configuration that has it covered. Posted in BlazeDS, Flex. Tags: BlazeDS, Flex, LCDS. No Comments [...]
[...] Note: In a real life application, you would not want to hardcode the endpoints of your services in your source code. You could use the XML configuration option to configure your endpoints in a more “externalized” fashion. More on this topic here. [...]
[...] À consulter sans attendre : l’article. [...]
Dynamically loaded BlazeDS configuration in Flex applications…
For people who wants to use server configuration (I mean channels, endpoints and remoting destinations from BlazeDs/LCDS services-config.xml and remoting-config.xml) loaded in runtime instead of common practice with reading configs in compile time Cris…