Posts in Category "FDS/LCDS"

Adobe Product – system requirement

If you have an older version of the product, please check the following links so that you can consider upgrade to a supported version.

Adobe Product – Supported Versions: http://www.adobe.com/support/programs/policies/supported.html

CF: http://www.adobe.com/products/coldfusion-standard/tech-specs.html

Flex: http://www.adobe.com/products/flex/tech-specs.html

LCDS: http://help.adobe.com/en_US/LiveCycleDataServicesES/3.1/Platform/LiveCycle_Data_Services_3.1_Platform_Martix.htm

FMS: http://www.adobe.com/products/flashmediaserver/productinfo/systemreqs/

AIR: http://www.adobe.com/products/air/tech-specs.html

Flash Player: http://www.adobe.com/products/flashplayer/tech-specs.html

Duplication session error

We have heard a number of customers who run into duplicate sessions error in LCDS/BlazeDS. To understand why and how it could happen, please see explanation here.

Basically, here are the causes and solution:
1. Cookies are disabled on the client.
solution: turn the cookies on the client.

2. Citrix had a policy to block session cookies.
solution: if you are using Citrix, need to turned it off.

3. The flex app makes two subsequent requests to the server before a session is established on the server for the first request.
solution: there are two options (See details here.):
a). the flex app should make the initial request and waits for its response (so a session is established) before making new requests.
b). trap the duplicate session error on the client and reissue the request. (See details here.)

4. Load balance tool cause subsequent requests to send to different server.
LCDS is a stateful server. This means that when a client makes an initial request to a server, the environment needs to make sure that all the requests from that client ends up on the same server from then on. In this case, you have to make sure your Load balance is configured so that all the subsequent requests from the same client is going to the same server. fail to do so will end up with this duplicate session error.
solution:: Make sure all the subsequent requests from a client end up at the same server.

Note, Some users may want to disable the duplicate session detection to get round the problem. Disabling the duplicate session detection is not an option because it’s a security risk. A single FlexClient is supposed to be associated with a single HTTP based session. If this is not enforced, your app could have some security risk. So, LCDS is checking the duplicate session for you and it should not be ignored. You should always find out and fix the underline problem instead of try to disable the duplicate session detection.

Demo for LCDS 3

To learn the new futures in LCDS 3, please see docs here

There are some good demos/videos listed below:

http://labs.adobe.com/technologies/livecycle_dataservices3/videos/

http://tv.adobe.com/watch/max-2009-develop/modeldriven-development-using-flash-builder-4-and-livecycle-data-services-es/

http://tv.adobe.com/watch/max-2009-develop/highperformance-realtime-messaging-with-flex-and-livecycle-data-services/

http://tv.adobe.com/watch/max-2009-develop/integrating-spring-with-blazeds-and-livecycle-data-services/

Accessing Spring beans from flex (FDS)

1. What is Spring? Why do we care about Spring?
Christophe Coenraets  ‘ s 30 minute test drive provides good answer to these questions. See details here.

2. Spring Configuration
You can follow the steps described by Christophe or Jeff Vroom, or you can follow the steps below which provide easier access to the required jars.
1). Download spring.jar and flex-spring-factory.jar to your machine, and put them into your flex app’s WEB-INF/lib directory.
2). Add the following into your flex app’s WEB-INF/web.xml file, inside <web-app> tag.

<context-param>
   <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
 <listener>
    <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class>
</listener>

3). Add the following into to WEB-INF\flex\services-config.xml inside <services-config> tag:
          <factories>
               <factory id="spring" class="flex.samples.factories.SpringFactory"/>
          </factories>
4). If you are using JRun as app server, set the following in WEB-INF\jrun-web.xml to avoid parser conflicting:
          <jrun-web-app>
              <load-system-classes-first>
true</load-system-classes-first>
          </jrun-web-app> 
Now you are ready to use flex to access Spring beans. 

3. Create Spring beans

We are going to use the sample code in singleManagedObject.zip. To understand the code and configuration, see ""How to get Single Managed Objects from a specified remote destination". In that example, we access data from DataService using an Assembler MyAssembler.java.  With the Assembler, we should be able to access Spring beans, right? Well, we are just a couple of steps away.

1). Create an interface (MyDAO.java)

Because we are trying to access Spring beans, we need to add an interface that represents all the methods we are going to use. From MyService.java we can see that there are only two methods for this sample, so MyDAO.java is going to be very simple: 

package myfds; 

import java.util.Collection;

import java.util.List;

import org.springframework.dao.DataAccessException; 

public interface MyDAO {       

            public List getProducts()  throws DataAccessException ;

             public MyBean getProduct(int myid)  throws DataAccessException ;

}

 

2). Modify MyService.java and MyAssembler.java

— copy MyService.java and save it as MyServiceSpring.java

Change the class to extends JdbcDaoSupport and implements the interface:

import org.springframework.dao.DataAccessException;

import org.springframework.jdbc.core.JdbcTemplate;

import org.springframework.jdbc.core.RowMapper;

import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;

import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

import org.springframework.jdbc.core.namedparam.SqlParameterSource;

import org.springframework.jdbc.core.support.JdbcDaoSupport;

public class MyServiceSpring extends JdbcDaoSupport implements MyDAO {

……

— copy MyAssembler.java and save it as MyAssemblerSpring.java

Change the class with setMyDAO():

import flex.data.assemblers.AbstractAssembler;

public class MyAssemblerSpring extends AbstractAssembler {

        private MyDAO myDAO;

        public void setMyDAO(MyDAO myDAO) {

                this.myDAO = myDAO;

        }

……..

3). Compile your java code

Remember to include spring.jar and flex-messaging.jar in the classpath,

C:\flex\jrun4\servers\default\samples2\WEB-INF\classes>javac -classpath ./;C:\fl
ex\jrun4\servers\default\samples2\WEB-INF\lib\spring.jar;C:\flex\jrun4\servers\d
efault\samples2\WEB-INF\lib\flex-messaging.jar  -Xlint myfds/*.java

Now we have the spring bean that we can access from flex, we need to register it with our flex app, and configure flex destination to point to the Spring factory.


4. Spring beans registration and flex destination configuration

1). Create applicationContext.xml and put it under your flex app’s WEB-INF directory. Here is the applicationContext.xml for this example:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

<!–define a data source to connect to your database –>

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">

    <property name="driverClassName" value="org.hsqldb.jdbcDriver"/>

    <property name="url" value="jdbc:hsqldb:hsql://localhost/flexdemodb"/>

    <property name="username" value="sa"/>

    <property name="password" value=""/>

</bean>

<!– define your service (methods) with a reference to dataSource –>

        <bean id="myServiceSpring" class="myfds.MyServiceSpring">

        <property name="dataSource" ref="dataSource"/>

        </bean>

<!– define assembler with reference (dependency) to myServiceSpring –>

<bean id="myAssemblerSpring" class="myfds.MyAssemblerSpring" singleton="true">

        <!–the property name myDAO should match the variable for interface MyDAO defined in MyAssemblerSpring–>

        <property name="myDAO" ref="myServiceSpring"/>

 </bean>

</beans>

 Note, myServiceSpring will be the soruce name you use in the destination you define below.

2). Configure destination

We have registered Spring factory in WEB-INF\flex\services-config.xml in step 2 #3).

 <factory id="spring" class="flex.samples.factories.SpringFactory"/>

Therefore we need to point the destination to spring factory. Add the following into WEF-INF\flex\Data-management-config.xml:

<destination id="myfds-spring">

          <adapter ref="java-dao" />

         <properties>

        <factory>spring</factory>

        <source>myAssemblerSpring</source>

                    <metadata>

                <identity property="myid"/>

            </metadata>

    </properties>

</destination>

Now, in flex mxml page, you can access the destination myfds-spring by doing something like this:

<mx:DataService id="ds" destination="myfds-spring" result="getData1(event)"/>

And call the methods in the Spring beans by using ds.getItem({myid:2})    

If you run myDataServiceSpring.mxml, you can get data from different method by click on different button.

Here is the simpleSpring.zip which incdules all the code.

How to get Single Managed Objects from a specified remote destination

Flex Campaign for Java Developers has launched on Monday, Feb. 13. This is good news for java developer who would like to make Flex app work with backend database.Christophe Coenraets  ’s 30 minute test drive  provides many examples about how to manipulate data with FDS. You can download the test drive server here.

Once you extracted fds-tomcat.zip , you can see flex samples that integrate with ActiveMQ , Spring 2 , Hibernate 3.2 , and HSQLDB 1.8 .  Sample 8 under testdrive folder demonstrated how to retrieve/create/update/delete data using FDS. The flex client code displays the collection managed objects retrieved from backend. However, users may have difficulty to get Single Managed Objects from flex app. It may not be clear how the identity is passed to the method. I was asked to create a sample to get Single Managed Objects from a specified remote destination. I am putting a simplified version of the example here to demonstrate how to do that.

1. Create java Assembler

1). Create your bean (MyBean.java)
First you create your bean with the data field you needed, and set/get method for each of them. 
2). Create MyService.java for your methods
For simplicity,  I have only defined two methods:
     getProducts()  – retrieve all data, returns a list
     getProduct(int myid) — retrieve data with myid as identity,  returns a single Object.
3). Create an Assembler (MyAssembler.java)
<The assembler extends AbstractAssembler class which is defined in flex-messaging.jar

public class MyAssembler extends AbstractAssembler {
        public Collection fill(List fillArgs) {
                      MyService service = new MyService();
                      return service.getProducts();
        }
public Object getItem(Map identity) {
                      MyService service = new MyService();
                      MyBean mybean =  service.getProduct(((Integer) identity.get("myid")).intValue());
                      System.out.println("mybean.myid="+mybean.myid);
                      return mybean;
        }

As we can see, fill() method calls getProducts(), and getItem() calls getProduct() from MyService.
Note,  MyBean mybean =  service.getProduct(((Integer) identity.get("myid")).intValue());
Here myid is the identity field.  It must match the identity property in your destination configuration:
<identity property="myid"/>

2. Compile your java code.
As we mentioned before, MyAssembler extends AbstractAssembler which is defined in flex-messaging.jar. So when you compile the java code, you must include flex-messaging.jar in your classpath.  This jar is included in your fds flex app’s \WEB-INF\lib directory.  For example:
C:\flex\jrun4\servers\default\samples2\WEB-INF\classes>javac -classpath ./;C:\fds-tomcat\webapps\ROOT\WEB-INF\lib\flex-messaging.jar -Xlint myfds/*.java

3. Mapping client-side objects to Java objects
This is a very important step, but easy to forget. Here are some key points from doc:
1). To represent a server-side Java object in a client application, you use the [RemoteClass(alias=" ")] metadata tag to create an ActionScript object that maps directly to the Java object. You specify the fully qualified class name of the Java class as the value of alias. This is the same technique that you use to map to Java objects when using RemoteObject components.
2).You can use the [RemoteClass] metadata tag without an alias if you do not map to a Java object on the server, but you do send back your object type from the server. Your ActionScript object is serialized to a Map object when it is sent to the server, but the object returned from the server to the clients is your original ActionScript type.
3). To create a managed association between client-side and server-side objects, you also use the [Managed] metadata tag or explicitly implement the mx.data.IManaged interface. The [Managed] metadata tag ensures that the managed Contact object supports the proper change events to propagate changes between the client-based object and the server-based object.
See MyBeam.as for code details.

4. configure destination in data-management-config.xml
add the following into your data-management-config.xml, parallel to other destination definition.
<destination id="myfds">
        <adapter ref="java-dao" />
        <properties>
            <source>myfds.MyAssembler</source>
            <scope>application</scope>
            <metadata>
                <identity property="myid"/>
            </metadata>
            <network>
                <session-timeout>20</session-timeout>
                <paging enabled="false" pageSize="10" />
                <throttle-inbound policy="ERROR" max-frequency="500"/>
                <throttle-outbound policy="REPLACE" max-frequency="500"/>
            </network>
        </properties>
    </destination>
 
Note: source should point to the full qualified class name of your assembler.
         Identity should match the identity you are passing in Assembler:
         MyBean mybean =  service.getProduct(((Integer) identity.get("myid")).intValue());

5. create flex page to display the data (myDataSerivce.mxml)
1).  Retrieve data
        <mx:ArrayCollection id="mydata1"/>
        <mx:DataService id="ds1" destination="myfds" result="getData(event)"/>
        <mx:Button  id="bt1" label="Get data from fill method" click="ds1.fill(mydata1)"/> 
        <mx:Button  id="bt2" label="Get data from getItem method" click="ds1.getItem({myid:2})"/>
— We first define a DataService ds1 which is mapped to destination named myfds. This should match <destination  id="myfds"> in data-management-config.xml.
—We call ds1.fill(mydata1) to populates an ArrayCollection mydata1, and use it as dataProvider of the datagrid.
    <mx:DataGrid dataProvider="{mydata1}"  width="300" height="100%" >
—We use ds1.getItem({myid:2}) to get single Object based on the dentity myid  we passed into getItem.
2). We use a result handler getData(event) to handle the data we retrieved from DataService. This will make sure that your event is trigged after the data has returned.  
Now let’s look at resulte handler getData():
   private function getData(event:ResultEvent):void{
           if(myButton == "bt1"){
                       prodId.text = event.result[1].prodID;
                       firstName.text = event.result[1].firstName;
                       lastName.text = event.result[1].lastName;
             }else{
                        prodId.text = event.result.prodID;
                        firstName.text = event.result.firstName;
                        lastName.text = event.result.lastName;    
              }
   }
Because fill() method returns an ArrayCollection, getItem() returns a single object, so we have to treat it differently. To figure out which method is called by the user, we add EventListener to the button, and record the button id.
     private function init():void{
              bt1.addEventListener(MouseEvent.CLICK,clickHandler);
              bt2.addEventListener(MouseEvent.CLICK,clickHandler);
      }
      private function clickHandler(event:MouseEvent):void{
               myButton = event.currentTarget.id;
       }   
Now, when you click different button, different data will be displayed in "User Details" TitleWindow.

6. To test the sample:

1).  Unzip singleManagedObject.zip to your machine . Put myfds folder under your flex app’s WEB-INF/classes directory. Put myDataService.mxml and MyBean.as under you flex app’s root directory.
2). Double check the step 4 mentioned above. Restart your flex app server if needed.
3). Run myDataService.mxml, click on the two buttons and see different data displayed.

7. Troubleshooting

If there are no erros client side, but can’t get data to retrun from the server side, check the following:

1). double check step 4 mentioned above, make sure your destinatio id, sourceand identity property are defined correctly. Also, make sure your database connection is valid and qurey statement are correctly retrieving data.

2). Trun on server side debug bysetting log level to debug in services-config.xml:

<target class="flex.messaging.log.ConsoleTarget" level="Debug">

Using FDS 2 with Tomcat

When using FDS 2 with Tomcat, there are extra files to install and configure. Please see flex install doc

1. About JOTM:
You must install JOTM from http://jotm.objectweb.org, and make sure you copy the JAR files from jotm-root/lib to tomcat-root/common/lib. The jar files are:

* jotm.jar
* jotm_jrmp_stubs.jar
* ow_carol.jar
* jta-spec1_0_1.jar
* jts1_0.jar
* objectweb-datasource.jar
* xapool.jar
* howl.jar
* commons-cli-1.0.jar
* connector-1_5.jar

To get JOTM configurate correctly with flex samples, see this link.
If you need to configure JDBC and transactions in Tomcat with JOTM, see this link.

2. About JMX
If you are using jdk 1.5. and up, then you don’t need to do anything about this. You will only need to install JMX if you are using JDK 1.4.x.

How to access database from flex 2

We often hear people asking about how to config datasource in flex to connect to a database. It is a miss conception to think that you need to config a datasource in flex and can use that datasource to connect to a database. Then how does flex app access data from a database? Flex does not connect to DB directly, but thru Java or other means. The doc has all the details regarding this topic, and has a sample of using PHP. But it may not be clear for people who are not familiar with J2EE to connect using java. Here is the steps to create access to database using Java.

Basically, there are three steps you need to accomplish in order to communicating with database from flex.

1. Write java code to communicate to the database. We usually call this an Assembler. In here, you provide the information about what database and jdbc driver you are connecting to, and create a connection to it.

2. Then config a destination which point to the Assembler in data-management.xml. Any flex app uses this destination will use this Assembler, and connecting to the same database.

3. In your flex code, you reference the data service like this:
dsEmployee = new DataService(“crm.company”);
here crm.company is a destination defined in step 2.

Now, Let us look at the sample code included in the samples.war to see how it is done. Let us look at the crm sample in dataservice.

1. Open dataservice\crm\companyapp.mxml, In there you can see the following code:

dsCompany = new DataService(“crm.company”);
// if hibernate is used, change the destination of the data service
// dsCompany = new DataService(“crm.company.hibernate”);
dsCompany.addEventListener(ResultEvent.RESULT, companyResultHandler);
dsCompany.addEventListener(FaultEvent.FAULT, faultHandler);
dsCompany.addEventListener(DataConflictEvent.CONFLICT, conflictHandler);
dsCompany.autoCommit = false;

Here we are using a dataService named “crm.company” for our app.

2. Open WEF-INF\flex\data-management.xml, we can see crm.company is defined as:

<destination id=”crm.company;”>
<adapter ref=”java-dao” />
<properties>
<source>samples.crm.CompanyAssembler</source>
<scope>application</scope>
….

This destination point to java class amples.crm.CompanyAssembler. This is our Assembler.

3. Let us see how the Assembler is constructed.
— go to WEB-INF\src\samples\crm\CompanyAssembler.java, we can see :
CompanyDAO dao = new CompanyDAO(); //using CompanyDAO class
— go to CompanyDAO.java, we can see
c = ConnectionHelper.getConnection(); //using ConnectionHelper class
— go to ConnectionHelper.java, we can see the code to connect to database:

private ConnectionHelper()
{
try
{
Class.forName(“org.hsqldb.jdbcDriver”);
// Obtain a path to WEB-INF/classes/samples/crm
String str = URLDecoder.decode(getClass().getClassLoader().getResource(“samples/crm”).toString(),”UTF-8″);
// Create HSQLDB JDBC URL pointing to WEB-INF/db/crm/crm (where the last crm is the datanase name)
url = “jdbc:hsqldb:” + str.substring(0, str.indexOf(“classes/samples/crm”)) + “db/crm/crm”;
}
catch (Exception e)
{
e.printStackTrace();
}
}

This is the core of the Assembler. This is where you tell flex which database to connect.

The most important information you need to provide are the driver name and the URL. Each database has different driver name and URL, you have to make sure you are using the correct name and format. Here is a list of driver name and example of URL:

#MySql
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test

#Oracle
#driver=oracle.jdbc.OracleDriver
#url=jdbc:oracle:thin:@test:1521

#Sybase Enterprise
#driver=com.sybase.jdbc3.jdbc.SybDriver
#url=jdbc:sybase:Tds:localhost:2048/test

#Sybase Anywhere
#driver=com.sybase.jdbc3.jdbc.SybDriver
#url=jdbc:sybase:Tds:localhost:2638/test

#Informix
#driver=com.informix.jdbc.IfxDriver
#url=jdbc:informix-qli://localhost:50000/test:informixserver=testserver

#MS SQL
#driver=com.microsoft.jdbc.sqlserver.SQLServerDriver
#url please see http://msdn2.microsoft.com/en-us/library/ms378428.aspx

Running Flash remoting sample on .NET

When running the Flash remoting sample on .NET, for example, http://localhost/flashremoting/samples/html/default.htm
you may see the page displaying “Loading … â€?, and hanging there forever. What’s the problem?

Well, here is a check list for this issue:
1. make sure you have the Microsoft .NET Framework SDK 1.1 installed on your machine. Flash Remoting will not work properly without the SDK.

2. In IIS console, right click on flahsremoting directory, make sure the URL is point to c:\inetpub\wwwroot\flashremoting, and click on the “Createâ€? beside the “Application nameâ€?, to make it a web app. And then restart the IIS.

3. Because the .net is compiling everything when you request a page at the first time, so it may take a while to display the content. So you need to make sure you leave enough time for the sample to process. Leave it there for 2 to 3 minutes to make sure it has enough time to run through before you cancel it.

Step 2 is the important one. In general, the installation should create the flashremoting as a web site. But sometimes that doesn’t happen, so you need to manually change it in the IIS console as described in step 2.

Make Flash Remoting work with Flash MX 2004

Do you find that the flash remoting code you developed using Flash MX doesn’t work with Flash MX 2004? If you do, you are not alone. The following explains why it is not working and how to make it work again.

Basically, the reason your code doesn’t work in Flash MX 2004 is because your code was written in ActionScript 1.0, but Flash MX 2004 is using ActionScript 2.0.

JRun installation includes some flash remoting samples. These samples seams to work with Flash MX and Flash MX 2004. Those samples were written in AS 1.0, how come they work with Flash MX 2004? The answer is because the samples included the compiled swf files. If you rename or delete the swf files, and try to compile those samples in Flash MX 2004, you will get compile error.

To make the code written in AS 1.0 to work with Flash 2004, you need to install “Flash Remoting Components ActionScript 1.0 for Flash MX 2004 and Flash MX Professional 2004â€? FlashRemotingComponents-win-en.exe from

http://www.macromedia.com/software/flashremoting/downloads/components/

If you are writing new code, it is the best to write in AS2.
To use the AS2.0 version you, you need to download the flashremoting_comp_as20-win-en.exe from

http://www.macromedia.com/software/flashremoting/downloads/components/

then, there are couples of more things you need to do. I haven’t tried this myself, but here seams to be the steps you need to do:

1. drag the RemotingClasses by doing the following:

From the open fla file in flash, go to Window — > Other Panels –> Common Libraries –> Remoting
Then drag the RemotingClasses on the stage of your movie. You can delete it off the stage and it will stay in your library.

The RemotingDebugClasses is for debugging during testing. You may want to remove this from your library when you go to production to reduce the file size.
See http://www.actionscript.org/forums/archive/index.php3/t-58195.html

2. You need to use
import mx.remoting.Connection;
import mx.remoting.NetServices;

Instead of #include “NetServices.as” because it is deprecated.