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.

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.
Bedava herşey burada
Kral oyunun en mükkemmel sitesi
I am getting total time in MessagePefirmanceUtils as
-ve. Is there any compatability issues of lcds with Java 1.6
Thanks for the valuable information. Recently i tried switching my applications to a different server and found the BlazeDs annoying. Now i am running in my new server. Thanks for the solution.
Thanks
Collin paul
Learn Forex
Since i’m just getting started, can you suggest a good beginner’s tutorial on this subject?
Hi,
I am new to Flex, and I appreciate your information here.
However, I am in a fix as to how you supply “destination” information if you do not have a services-config.xml.
I am trying to setup a coldfusion-flex project and I am getting an error “No destination with id ‘product’ is registered with any service.”
public var productsRO:RemoteObject;
public function ProductsService()
{
var channelSet:ChannelSet = new ChannelSet();
channelSet.addChannel(new AMFChannel(“ProductsService”,”http://cfweb.dev/flex2gateway/”));
productsRO = new RemoteObject();
productsRO.channelSet = channelSet;
productsRO.destination = “product”;
}
I am using the above code for setting up my Product_RO
I will greatly appreciate it if you can provide an answer for this, as I would like to decouple from DEV machine’s coldfusion setup vs Prod-server CF setup
Thanks,
AAP
Just an add on from the Brian comment. The Swiz system has been updated and is even better now. Thanks for the info.
truly one of a kind! thanks
forex Trading is not easy. You can become a good forex trader though dedication and by treating forex trading as you would any other skill. The reality is that it is hard work and must be treated with the same amount of seriousness as you would any other career.
How about connecting from another server and not form inside tomcat? I can’t point to a generic gateway like I can in php, there is no context root so the http://blahblah.com/context-root/messagebroker/amf is missing a part.
Any insight on this?
This works fine when I run the app in Flash Builder, but I get a ‘file not found’ error when I build the app and deploy it, even though I see the file in my ‘config’ directory.
Is there some additional permission and/or config to get the Flex app to read the file when the app is deployed? I don’t have this problem with svg files I’ve embedded from an ‘assets’ directory.
Thanks a lot,
it’s a good solution for flashdevelop users, because flashde
Thanks a lot,
it’s a good solution for Flashdevelop users too…
Life-saving Information! Thank you.
Thank you for the great info,
Incredible – never seen before Forex software just launched!
“Auto Trend Forecaster”
http://autotrendforecaster.yolasite.com/
This is one the most profitable
Forex Trend indicators you can get today!
!
Get your own PR 9 Edu blogs and backlinks. Get listed on google first page for your keywords in a matter of hours!
Visit: http://edu-blogs.yolasite.com
Get yours whilst special offer lasts
Hi Christophe,
Another (easy) way to get ‘run time flexibility’ in an AIR application is:
- compile with the services-config.xml
- leave the ‘{server.name}’ in tact in services-config.xml
- at run time, search/replace ‘ServerConfig.serverConfigData’ with what you want (e.g. connecting to a different server)
// Search/replace server in services-config compiled
var serverConfigData:XML = ServerConfig.serverConfigData;
// Convert to String and replace {server.name} with actual server
var serverConfigDataAsString:String = serverConfigData.toXMLString();
serverConfigDataAsString = serverConfigDataAsString.split(“{server.name}”).join(serverName);
ServerConfig.serverConfigData = new XML(serverConfigDataAsString);
From here on the AIR application behaves as if you had the server name hard coded in the services-config.xml.
This is truly one of the best blogs I have ever come across. Very well written, precise and to the point. Thanks to the author for this brilliant share.
Just bookmarked this link in my browser. I will definitely visit this site later to read some more quality blogs. Thanks.
God bless you Christophe Coenraets.
I like your work in Flex community ..
I’m wondering if we can read an external xml data and use it in Bean configuration (Beans.mxml) before swiz initialization. Making endpoint configuration and channel switching from amf to amfsecure much easier ??
Very useful blogpost. Do you know whether it’s possible to enable “mx.messaging.messages.MessagePerformanceUtils” using the above method? It’s a read-only property.
Very useful blogpost! However, do you know whether it’s possible to set values for recordMessageTimes/Sizes using this method (used in conjunction with mx.messaging.messages.MessagePerformanceUtils)? They seem to be read-only values on Channel. Best regards, Seppe
My apologies… found the answer :-) The read-only properties can be set using “applySettings()”
http://ndpar.blogspot.com/2009_06_01_archive.html