Archive for the ‘Flex’ Category
BlazeDS, LCDS and integration with existing application
Posted by cornel | Filed under Flex, Java, LCDS/Blaze DS
UPDATE: Well, I just published my post and I received the following message on YM: You forgot to write that you have to pay money in order to use these products.
I do not want to write a half a page now on licensing so I will be brief (please check the Adobe site for exact information):
BlazeDS is free and opensource. You do not have to pay anything to use it. If you want to buy Adobe support that’s fine, if not you can find books, articles and samples related to this product. LCDS it is a commercial product but it is free if you are using it for one processor, so you can evaluate it and decide if it’s ok for you or not.
Some time ago, after a discussion with several Java developers I realized that they thought that BlazeDS and Livecycle Data Services were some kind of special servers that should be installed separately from the application server – something like Lightstreamer. They also thought that in this case they would have to write additional code in order to do the integration between servers. And one week ago I even met some guys using webservices in order to retrieve data from the Java backend because they did not want “to depend on some Adobe server”. There is nothing wrong with using webservices in Flex, in some cases it is your only option (for example if you want to use Amazon search API), but it is much slower than using BlazeDS remoting. So if you need to connect your Flex application to your java backend I strongly recommend using remoting or the data management feature provided by LCDS.
So I’ve decided to write two posts, one describing how to integrate BlazeDS or LCDS into your existing application, the second one on how to integrate or expose the existing Java code in order to be used in remote calls or for data synchronization. I will also try to cover the aspect of integrating Hibernate and Spring.
Both BlazeDS and LCDS are packaged as WAR applications, they are just simple Java applications that can be deployed in any application server. The procedure to install them is described in so many places so I don’t want to insist on that – take a look, for example, at my colleague’s post. Instead I will write what to do when you already have an application packaged as a WAR and you intend to do the integration with BlazeDS/LCDS.
For BlazeDS there are three steps:
a)Copy the folder called “flex” from blazeds.war\WEB-INF into your WEB-INF folder. This folder contains the configuration files needed by BlazeDS. Of course you can copy in other location if you want but for the sake of simplicity leave them under WEB-INF
b)Take a look at the folder named “lib” at blazeds.war\WEB-INF\lib . It contains all the jar files needed by BlazeDS:
backport-util-concurrent.jar
cfgatewayadapter.jar – you don’t need this it if you do not use ColdFusion
commons-codec-1.3.jar
commons-httpclient-3.0.1.jar – used by the proxy services, if you use only remoting it’s optional
commons-logging.jar
concurrent.jar
flex-messaging-common.jar
flex-messaging-core.jar
flex-messaging-opt.jar
flex-messaging-proxy.jar
flex-messaging-remoting.jar
xalan.jar
You should copy these libraries into your WEB-INF\lib folder. If you already use some of them (Jakarta libraries for example) you should keep the latest version (you can check the version by looking in the manifest.mf file.
c)Add the following entries into your web.xml file (taken from BlazeDS web.xml file):
<!– Http Flex Session attribute and binding listener support –>
<listener>
<listener-class>flex.messaging.HttpFlexSession</listener-class>
</listener>
<!– MessageBroker Servlet –>
<servlet>
<servlet-name>MessageBrokerServlet</servlet-name>
<display-name>MessageBrokerServlet</display-name>
<servlet-class>flex.messaging.MessageBrokerServlet</servlet-class>
<init-param>
<param-name>services.configuration.file</param-name>
<param-value>/WEB-INF/flex/services-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>MessageBrokerServlet</servlet-name>
<url-pattern>/messagebroker/*</url-pattern>
</servlet-mapping>
The same steps are valid also for LCDS with several small differences:
a)The same folder flex should be copied but for LCDS it also contains some SWC libraries and one more configuration file
b)The libraries shipped with LCDS are:
acrobat-core.jar – you don’t need this if you plan to use only data management and remoting
acrobat-core-charset.jar – you don’t need this if you plan to use only data management and remoting
backport-util-concurrent.jar
cfdataservicesadapter.jar – you don’t need this if you do not use ColdFusion
cfgatewayadapter.jar – you don’t need this if you do not use ColdFusion
commons-codec-1.3.jar
commons-httpclient-3.0.1.jar – used by the proxy services, if you use only remoting it’s optional
commons-logging.jar
concurrent.jar
flex-acrobat
flex-messaging-common.jar
flex-messaging-core.jar
flex-messaging-data.jar
flex-messaging-data-req.jar
flex-messaging-opt.jar
flex-messaging-proxy.jar
flex-messaging-remoting.jar
c)This step is identical for both BlazeDS and LCDS.
In the second post on this subject I will show how to integrate your existing Java code so it can be invoked remotely or used with the data management feature.
AMF3 and zlib compression
Posted by cornel | Filed under Flex, Java
Yesterday I was reading the Exadel documentation and in the chapter describing AMF format I’ve read the following things: “AMF objects are of a very small volume due to the fact that they are compressed using zlib”. I sent them an email regarding that and explaining that the DEFLATE algorithm is not used in AMF serialization, so there is no zlib connection). They told me that they took the information from web, and I see what the mean – if you will search for “AMF objects are compressed using zlib” you will find a lot of references.
Peter Farland (lead engineer for the SDK team) has already posted several comments on blogs and on the Zend Framework wiki regarding that and I will write it again here: there is no connection between the zlib algorithm and AMF format. Yes the serialization uses some kind of compression (for instance writing references for identical strings) but not zlib.
However the developer is free to compress all HTTP responses using zlib (when supported) so the serialized AMF data will be compressed also. Or you can choose to apply DEFLATE only on some data (like big strings) – you can read here my post related to that.
Flash and Javascript communication using ExternalInterface
Posted by cornel | Filed under Flex
I’ve decided to write a very simple example showing communication between JavaScript and ActionScript using Externallnterface. For more complex things one can use the Flex Ajax Bridge but for simpler ones ExternalInterface is good enough. The communication is both ways: you are able to call any JavaScript function from ActionScript and any exposed ActionScript function from JavaScript (exposed means that you will have to register the name of the function using the ExternalInterface api).
It’s possible not only to call methods but also to pass parameters and receive return values. It is not possible however, to automatically catch errors – you will have to catch them manually and serialize them between ActionScript and JavaScript.
To check the supported browsers check this link.
There are two methods in ExternalInterface: call (for calling JavaScript functions) and addCallback in order to register an ActionScript method as callable. Here is some sample code (full source code here):
public function init():void{
if (ExternalInterface.available)
ExternalInterface.addCallback("setText", setText);
}
public function setText(text:String):void{
userName.text = text;
}
public function callText():void{
if (ExternalInterface.available) {
ExternalInterface.call("setText",userName.text);
}
}
The addCallback methods recieves two parameters: first one is the name which can be used by JavaScript in order to call the function and the second one the function.
The call method receives N parameters: the first one is the name of the JavaScript function, the other ones are the parameters to pass to the function.
The sample can be tested here – it shows text synchronization between two textfields, one is an HTML textfield and the second one is a Flash control.
Bringing data into Flex applications – introduction
Posted by cornel | Filed under Flex, Java, LCDS/Blaze DS
This article will describe the most common ways to bring data into a Flex application and will present the advantages and disadvantages of each approach. It assumes that the reader has a basic understanding of the Flex language.
Unlike a classic web application (by classic I mean pre AJAX) where the pages are generated on the server the Flex application is loaded at startup and makes calls in order to load or to save data. Of course a Flex application can also make requests in order to load other Flex modules in the same way a Java application can dynamically load JAR libraries but that is a subject for a different article.
Some of the presented solutions are server agnostic – you can use anything on the backend – others assume that you have installed a Java application server where you can deploy various solutions including BlazeDS, Livecycle Data Services, GraniteDS, Cinnamon, WebORB etc.
a)Opening a socket connection between the Flex application and the backend.
A socket connection It is the most low-level solution and at the same time the one most flexible. You will have to define your own protocol and how to serialize data (or use the AMF/Hessian protocols). In most cases, you should use this solution only if you have a very specific business need and the existing solutions do not meet your requirements).
You can use Apache MINA if you intend to do that. For example Red5 Flash server was written using the MINA framework.
Bellow is a simple code snippet that shows how to create a socket and how to read or write data:
public function initConnection():void{
CursorManager.setBusyCursor();
Security.loadPolicyFile("xmlsocket://localhost:24");
socket = new Socket();
socket.addEventListener( Event.CONNECT, onConnect );
socket.addEventListener(ProgressEvent.SOCKET_DATA, socketRead);
socket.addEventListener(ErrorEvent.ERROR, errorHandler);
socket.addEventListener(IOErrorEvent.IO_ERROR, errorHandler);
socket.addEventListener(SecurityErrorEvent.SECURITY_ERROR, errorHandler);
socket.connect("localhost", 23);
}
public function socketWrite(event:Event){
socket.writeUTF(inputName.text);
socket.flush();
}
public function socketRead(eventrogressEvent){
while ( socket.bytesAvailable ) {
var data:String = socket.readUTF();
Alert.show(data);
}
}
You probably noticed the line Security.loadPolicyFile(“xmlsocket://localhost:24″); By default a Flex application can open connections only to the same domain from where it was loaded and on the same port. In order to be able to initiate connections to another domain a file named crossdomain.xml must exists on that server. This file specifies the what resources are available and for what domains. In our case the policy file will allow that the all the SWF loaded from any domain are allowed to connect to the port 23
<cross-domain-policy>
<allow-access-from domain="*" to-ports="23" />
</cross-domain-policy>
For more details regarding the policy files and Flash security, see this documentation.
b)Using REST and SOAP services (via HTTPService and WebServices components)
REST and SOAP services works with any type of server-side technology – also these technologies are standard and most of the biggest service providers(Yahoo, Amazon, Google, Flickr, eBay) expose their API through both of them . There is an endless debate on when to use REST and when to use SOAP but that is beyond the scope of this article. Instead I will present some samples on how to use them.
As with the sockets example, because the Flex application can initiate requests only to the same domain from where it was loaded you’ll need a crossdomain.xml file on the server where the services are located. Obvious you cannot put a policy files on every server so use the following approach: connect to the back-end server from where the Flex application was loaded and use that server to make the request – after that send the result back to the Flex application. For that you can use an existing product – BlazeDS or another solution.
Below is a sample code showing the two mxml tags used to call REST and SOAP services:
<mx:HTTPService id="resultHttpService"
url="http://www.sampledomain.com/query.jsp?quote=ADBE" />
<mx:WebService id="resultWebService"
wsdl="http://www.sampledomain.com/quotes?wsdl" />
In this case I am connecting directly to sampledomain so the first time the Flash Player will check for crossdomain.xml to see if the server allows the request.
In order to use the proxy approach (use the server to do the request) I will modify the code:
<mx:HTTPService id="resultHttpService" destination="HTTPDestination" useProxy="true" />
<mx:WebService id="resultWebServive" destination="WebServiceDestination" useProxy="true" />
and in proxy-config.xml I will add the destination definition:
<destination id="resultHttpService">
<properties>
<url>http://www.domain.com/query.jsp?quote=ADBE</url>
</properties>
</destination>
<destination id="ws-catalog">
<properties>
<wsdl>http://www.domain.com/quotes.wsdl</wsdl>
<soap>*</soap>
</properties>
<adapter ref="soap-proxy"/>
</destination>
In the REST example it is very important to notice that due to Flash Player limitations you are allowed to use only GET and POST methods, and any return code other than 200 will generate a fault. To overcome these limitations you can write your own proxy server, or better still, use one already written (BlazeDS for example).
c)Using remoting
Remoting technology allows developers to directly invoke methods on the backend server. Initially this was possible only with Java and Coldfusion but after that the format used to package data (AMF3) was made open source and different implementations have appeared for PHP, Python, Ruby and .Net.
Compared with Web Services one of the biggest advantage of using remoting is the bandwidth savings – data is compressed using a binary format which is much more compact then the plain text format. The most used format is created by Adobe and is called AMF3 but there is also another alternative called Hessian. Both formats are open source. The most important difference between them is that AMF3 serialization/deserialization is included in the Flash Player, while when using Hessian you will have to add some libraries to our Flex project.
Below I will present some examples for Java language, using BlazeDS and AMF.
The mxml tag from the Flex application looks the same as the ones used for calling webservices – the main attributes are the id and the destination
<mx:RemoteObject id="productService" destination="ProductService"/>
The destination is configured into the file remoting-config.xml:
<destination id="productService">
<properties>
<source>
com.test.services.ProductService
</source>
</properties>
<adapter ref="java-object" />
</destination>
The remote object allows you to call methods on the Java object associated with the corresponding destination. Everything else is transparent from the user’s point of view (including the conversion between ActionScript and the Java objects and the serialization mechanism that can handle complex objects graph). You will only need to declare the mapping between the ActionScript and the Java objects using the [RemoteClass] metadata:
package com.test.model{
[RemoteClass(alias="com.test.model.Product")]
public class Product{
public var id:int;
public var name:String;
}
}
Before you start to use remoting it’s a good idea to read this link describing data types conversion between Java and ActionScript.
It is important to notice that on every I/O operation also the remote method is invoked asynchronously so you will need to register handlers for the result and fault events.
d)Using messaging
There are currently several messaging solution on the market for the Flex applications: BlazeDS (and the commercial version Livecycle Data Services) , Granite Data Services and WebORB. All of them also have integration with JMS servers.
With messaging, a Flex application can connect to a message destination on the server (specified in messaging-config.xml) and can exchange messages with the server or with another clients (using the server as a proxy). You can use messaging to have the server push messages to the clients (for example, in an application that displays the latest stock prices) and you can use it for collaboration between clients (for example a chat application).
One of the most important things when working with messaging is choosing the proper communication channel in order to obtain real time messaging. BlazeDS server supports HTTP streaming and polling (short and long) over AMF and HTTP channels. HTTP streaming is the best way to obtain data in real time but because of the limitations from the servlet model it keeps one thread open per connection. The commercial version (Livecycle Data Services ES) overcomes this limitation with the help of NIO channels (RTMP and NIO HTTP).
Below is a code sample that shows the main tags used for messaging:
<mx:Producer id="producer" destination="chat"/>
<mx:Consumer id="consumer" destination="chat"/>
The destination chat is defined below:
<default-channels>
<channel ref="my-rtmp"/>
<channel ref="my-streaming-amf"/>
</default-channels>
<destination id="chat">
<properties>
<network>
<!--The session timeout for inactive HTTP sessions–>
<session-timeout>0</session-timeout>
</network>
</properties>
</destination>
Detailed information regarding messaging can be found in the Messaging Service chapter of the BlazeDS developer guide.
e)Using Data Management Service
Data Management Service is a feature provided (as of the writing of this article) both in Livecycle Data Services ES and WebORB. Both products offers a framework called Data Management however the architectures differ – in this article I will discuss only the Data Management framework provided by Livecycle Data Services. It operates at a much higher level than the messaging and RPC services. While it can be used for different types of applications it provides the most value for data intensive applications (especially where collaboration is very important). It is designed to solve several important challenges:
- synchronizing data on clients with the server without having to write CRUD methods
- automatic or manual data synchronization between clients
- conflict handling, paging data sets, working with offline applications and synchronizing the data when the application is online again
One can make a comparison between Data Management and Hibernate – both frameworks allow the developers to concentrate on defining the domain model and working with it without spending too much time on problems like how to persist, load, version and synchronize data. Hibernate deals with data persistence into database, Data Management with data persistence and synchronization between client applications and the server. There is also integration between these two frameworks and I’ve attached a fully working example showing that.
As with messaging,it is very important how to choose the correct communication channels (especially for automatic synchronization feature). The same choices described in the messaging example apply here.
Here is a simple example that shows how easy it is to create an application for editing a table:
The Flex code:
<?xml version="1.0" encoding="utf-8">
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" initialize="init();" >
<mx:Script>
<![CDATA[
import test.*;
import mx.collections.ArrayCollection;
import mx.data.events.*;
import mx.events.*;
import mx.data.*;
var companyDataService = new DataService("test.Company");
[Bindable]
var companyArray:ArrayCollection = new ArrayCollection();
function addCompany():void{
var company:Company = new Company();
company.name="<new company>";
companyArray.addItem(company);
}
function deleteCompany():void{
var company:Company = companyGrid.selectedItem as Company;
if (company==null)
return;
companyDataService.deleteItem(companyGrid.selectedItem);
}
function save():void{
companyDataService.commit();
}
function revert():void{
companyDataService.revertChanges();
}
function init():void{
companyDataService.fill(companyArray,"mainFill",[]);
companyDataService.autoCommit=false;
}
]]>
</mx:Script>
<mx:VBox width="100%" height="100%" horizontalAlign="center" >
<mx:DataGrid id="companyGrid" width="40%" height="40%" dataProvider="{companyArray}" editable="true" textAlign="center">
<mx:columns>
<mx:DataGridColumn dataField="id" headerText="Id" editable="false"/>
<mx:DataGridColumn dataField="name" headerText="Company"/>
</mx:columns>
</mx:DataGrid>
<mx:HBox horizontalAlign="center" width="100%">
<mx:Button label="+" click="addCompany();"/>
<mx:Button label="-" click="deleteCompany();"/>
</mx:HBox>
<mx:HBox width="100%" horizontalAlign="center">
<mx:Button label="Save changes" click="save();"/>
<mx:Button label="Revert modifications" click="revert();"/>
</mx:HBox>
</mx:VBox>
</mx:Application>
The definition of the DataService object is located in the configuration file data-management-config.xml
<destination id="test.Company" channels="my-rtmp">
<properties>
<source>flex.data.assemblers.HibernateAnnotationsAssembler</source>
<scope>application</scope>
<item-class>test.Company</item-class>
<metadata>
<identity property="id" />
</metadata>
<server>
<hibernate-entity>test.Company</hibernate-entity>
</server>
</properties>
</destination>
As you can see there are no remoting calls – after the collection companyArray is filled with data you can manipulate the data by adding new elements, deleting or updating elements. You have the option to call save when you want to persist the modifications or revert if you decides to discard them.
It is possible to work with more complex domain models (associations between objects) and you can find one example of this attached.
Data Management is the most appealing approach for bringing data into a Flex application, but like Hibernate case it has a steep learning curve. Documentation related to it can be found in LCDS developer guide.
The following table summarizes the advantages and disadvantages for each solution:
| Pros | Cons | |
| Socket communication | The most flexible approach. Allows you to write your own server using whatever technology do you want obtaining the best performance. | It takes a lot of time and money to define your protocol and write your server. It can be useful if you intend to communicate with an already written server or for cases in which you need extremely high performance |
| REST/SOAP services | Well established standards, you can wrote them once and consume them from most of the systems, not just Flex applications. Also most of the companies expose their api through REST and SOAP services | The overhead of parsing data (especially for SOAP) can be substantial |
| Remoting | Little overhead compared with web services. The bandwith used is also much smaller. Automatic conversion between Action Script and the Java objects (or another language). Increased productivity (number of code lines is reduced, also the development time) | Sometimes the data exposed through services needs to be consumed by a variety of applications – this is possible using web services but not with remoting |
| Messaging | Ability to implement collaboration features. Integration with JMS | There are relatively few solutions that implements messaging. As the writing of this article only BlazeDS/LCDS from Adobe and GraniteDS (if your backend is Java) and WebORB (if your backend is Java, PHP, .NET) |
| Data Management (LCDS) | The time needed to implement a data driven application is reduced. It offers solutions for collaboration, conflict detection, dealing with complex domain objects, pagination and lazy loading. It also offers integration with Hibernate and Spring | There is only one commercial product for this solution – LCDS from Adobe. It has a relatively steep learning curve |
I have also attached an archive containing one Flex Builder project showing the data transfer using sockets and also a more advanced case of data management use. For the rest of the cases I recommend that you download the most recent version of BlazeDS (look in samples folder) or LCDS (look in the lcds-samples folder). If you want to use non Adobe products you can try WebORB (look in examples/flex folder) or GraniteDS (I was not able to find a folder with samples in this product).
AIR and drag and drop
Posted by cornel | Filed under Flex
I’m working on an AIR application that uses not only the ability to drag and drop external files into the application but also to drag and drop objects internally. More specifically I’m using Ely Greenfield component in order to display some pictures. The component worked perfectly when included in a Flex application running in the Flash player and Firefox but when included in the AIR application everything was messed up. After digging into the code, I finally noticed that by default AIR uses a different implementation for drag and drop than the Flex application (NativeDragManagerImpl vs DragManagerImpl).
I was not able to make the component working at all with NativeDragManagerImpl. And, just when I thought that I was stuck I’ve found this bug on Adobe JIRA, together with a workaround. The workaround works; it is not very elegant but that’s it.
After playing a little bit more with the NativeDragManagerImpl I believe that the only decent solution is to use the described workaround if you plan to use AIR and internal drag and drop (also it seems that you cannot control the alpha level when using it).. and wait for Flex4 in order to have the bug fixed.
Transylvania JUG – Flex presentation
Posted by cornel | Filed under Events, Flex, Java
Last week I made two presentations (Introduction to Flex and Integration between Flex and Java) for Transylvania JUG , the first Java user group established in Romania, in the middle of Transylvania. There were about 60-70 developers asking a lot of questions. I knew that some of them knew Flex but I was surprised to see that some of them also have knowledge of LCDS and BlazeDS. The user group was founded only a few months ago but they succeeded to organize several meeting related to Flex, Groovy, TestNG.
I hope that in future this kind of meetings will become a regular thing in Romania and more active user groups will be founded. Romania has one of the largest developers communities in Eastern Europe – and meetings like this help people share information, establish new connections, and improve their applications.
A picture from the conference room:
And the user group logo:
Flex – improve search behavior in ComboBox components
Posted by cornel | Filed under Flex
Updated: After a discussion with the engineering team I filled this bug
The ComboBox component from Flex SDK does not perform a fancy search by default – for example if you press ‘A‘ it will go to the first element starting with ‘A‘, if you press ‘B‘ it will go the first element starting with ‘B‘ but if you press quickly ‘A‘ and ‘B‘ it will not display the first element starting with ‘AB‘ – instead if will display the first one starting with A and after that the one starting with ‘B’. I know that the HTML select control can do that and I’ve heard some people complaining because they are not able to do it in Flex so I planned to wrote the implementation.
There are two cases: the first one is when the drop down list is opened and the user is typing, the second one is when the drop down list is not opened but the focus is positioned on the ComboBox and the user is typing.
For the first case I extended the List component and I wrote a new findKey method. The dropdownFactory property of the ComboBox component will be set to the new class. The code is displayed below:
package com.test
{
import mx.controls.List;
public class ListSearch extends List {
private var previous:Number;
private var current:Number;
private var pressed:String=“”;
protected override function findKey(eventCode:int):Boolean{
current = new Date().time;
if ((current-previous)>500){
previous = current;
pressed = String.fromCharCode(eventCode);
return super.findKey(eventCode);
}else{
previous = current;
pressed = pressed + String.fromCharCode(eventCode);
return findString(pressed);
}
}
}
}
<mx:ComboBox id=“combo” dropdownFactory=“com.test.ListSearch”>
<mx:dataProvider>
<mx:Array>
<mx:String></mx:String>
<mx:String>AAAAAAAA</mx:String>
<mx:String>ABBBBBBB</mx:String>
<mx:String>ACCCCCCC</mx:String>
<mx:String>BBBBBBBB</mx:String>
<mx:String>CCCCCCCC</mx:String>
</mx:Array>
</mx:dataProvider>
</mx:ComboBox>
The second case proved to be much difficult..I do not know if I will be able to do it without rewriting the entire ComboBox component – too many of methods and members have the private access modifier so extending is not a solution. I’m still wondering how to do it.
I’m curious if anyone experienced this problem when trying to modify the default behavior of the ComboBox component (or another Flex component).
2 Responses to “Flex – improve search behavior in ComboBox components”
LiveCycle Data Services 2.6 – new features (3)
Posted by cornel | Filed under Flex, Java, LCDS/Blaze DS
Two new endpoints were introduced in LiveCycle Data Services 2.6: NIO AMF and NIO HTTP and with them one can have now a viable alternative to RTMP. While RTMP offers best performance for data push – offers a direct duplex socket connection between the client and server and does not need a dedicated thread for every connection it uses a non-standard port (2038) so sometimes it is blocked by firewalls. If the firewall restriction cannot be lifted the other options was to use servlet-based AMF and HTTP endpoints and use long polling or HTTP streaming to emulate real time communication. The scalability was very low compared with RTMP (maybe several hundreds/thousands compared with tens of thousand) because of the dedicated thread per connection.
With the new endpoints this problem was solved – by building a NIO server based on the JAVA NIO api this limitation was removed– now it is possible to handle the connections asynchronously. And you do not have firewall issues because they are using the HTTP port.
From the client point of view the NIO AMF and HTTP endpoints are equivalent to the old endpoints (AMF and HTTP) so you should not modify the existing applications (but you cannot share the FlexSession between channels using NIO HTTP endpoints and the ones using HTTP). After you download the Livecycle Data Services 2.6 you can find several examples of how to configure them in the services-config.xml file.
It is important to mention that these new endpoints were introduced only for LiveCycle Data Services and not for Blaze DS – so if you are using the last one you still have to deal with the limitations of the current servlet API (one thread per connection) – at least at the moment of writing this post. Probably the situations will change in future – Blaze is open source so anyone can contribute to the source code. There seems to be other several free options – GraniteDS and WebORB however I did not had yet time to test them.
Flex, Blaze DS and storing session data
Posted by cornel | Filed under Flex, Java, LCDS/Blaze DS
One of the biggest difference between the classical web applications (HTML/JS) and the rich ones (Java applets, Flex, Silverlight) is how can you store the state of the application.
With HTML applications we are used to using different hacks to store the state – either appending all the necessary information to the requests or storing the data on the server (and using a cookie or a session id to link the user and the information). Some even use a “dirty hack” and keep a small window open where you can store/retrieve all this information by using Javascript (yes, I have seen this unusual approach in several applications).
With Flex applications (and also with the other technologies mentioned before) the things are much simpler. You do not have several pages which are loaded from the server, instead you have an application that is loaded in the browser and can store the data using its internal data structures. The application will make requests to the server but only to exchange data (and in some situations to load modules), not to load whole pages. To make an analogy – it’s like having a HTML application composed of only one page that uses AJAX and JavaScript to load and build other pages (This is doable, I have seen a project where the guys were using this approach because of some strange requests from the client, but it was a nightmare to maintain and develop the application).
So you are able to store user preferences, user actions (for example the products added to a shopping cart) and other data directly into the client – the Flex application. It is more natural (in my opinion) than storing the data on the server and it is also much cheaper than buying expensive hardware for the middleware – you are using the client machine to store data so you are not overloading the server (think about having 100000 connected clients and session replication and you will understand what I’m talking about).
However there are several situations when you have to store a minimal amount of information on the server – the user identifier for example. After a successfully login authentication I have to store the user ID into the server session. After that this ID is used to check all the requests and to filter data that is sent to the client. Below I show you how to do that in Flex and what things you need to take into account. I’m using Blaze DS on the server side.
The FlexContext class can be used to access the FlexSession class which has several useful methods to set/get/remove attributes, to configure the timeout and session listeners, and so on. Here is some code that shows how to use them.
UserRoles userRoles = userHome.logIn(userName, passwd);
if (userRoles == null)
throw LoginFailedException("Invalid login");
FlexContext.getFlexSession().setAttribute("userId", userRoles.getUserId());
public Collection fill(List fillArgs, int startIndex, int numItems){
Integer userId = (Integer) FlexContext.getFlexSession().getAttribute("userId");
if (userId==null)
throw AuthenticationException("No logged user");
ASObject map = (ASObject)fillArgs.get(1);
Integer companyId = (Integer)map.get("companyId");
return new CompanyService().findProducts(
companyId,
userId);
}
Note: this is just a simple example how to use FlexSession. For user authentication and securing destinations read the LCDS developer guide, specifically the chapter titled “Securing destination”.
Important things to take into account when working with session data (taken from the developer’s guide):
- when using RTMP channel after a browser refresh the content of the FlexSession is lost; also the user will have to log in again
- you will have different FlexSession objects for HTTP, RTMP and NIOHTTP channels – so consider working with only one type of channel
- if you logged in using a RTMP channel you must log in again when switching to another type of channel
- FlexSession is not cluster aware – if a client connects to a different server in the cluster, the client receives a new FlexSession and the client will have to login again
LiveCycle Data Services 2.6 – new features (2)
Posted by cornel | Filed under Flex, Java, LCDS/Blaze DS
This is the second post describing several new features in the 2.6 version of LiveCycle Data Services– I will present several features that are related to managed associations.
In the current version several new parameters were introduced: read-only, load-on-demand, page-size, paged-collection and paged-updates.
The first one should be used for bidirectional relationships and it has the same meaning as setting inverse=”true” for a Hibernate association (the assembler will use only the other side of the relation in order to take modifications into account).
The other ones are used to improve the performance of managed associations. In the previous version you could improve it in several cases by using the “lazy” parameter. When set to true and applied to a one-to-one, one-to-many, or many-to-many association the client, by default, will load by default only the ID of the objects – the whole object will be loaded only when it is accessed for the first time. This can improve performance, but if you have a large collection you will still have to load a lot of information from the database to obtain all the ID’s and send them to the client
The new parameters remove this limitation. When you set load-on-demand for an association no values are sent to the client until the first time the association is accessed (it has the same effect as the lazy parameter for Hibernate managed collection). The page-size and paged-collection parameters are used to implement page-by-page fetching from the database/server – very important for large sets. The last one, paged-updates, controls the way in which the modifications from the client are sent to the server. If the value is false the entire collection is sent when some objects are removed or added, if true only the ID’s of these objects are send to the server. This parameter is automatically set to true if also page-size is set to true.
The effect of these parameters can be noticed especially when working with large collection – I performed some tests with a collection that has about 50000 elements (loaded in a datagrid) and it worked smoothly.
http://www.adobe.com/cfusion/exchange/index.cfm?event=extensionDetail&extid=1047291
August 30th, 2008 at 10:41 am Hi Dimitrios,
Thanks for letting me know – it’s very close to what I’m looking for. I will try to see if I can modify a little bit the current behavior (to add a dropdown arrow).