SQLAssembler: create a Flex and Java application with LCDS (LiveCycle Data Services) without server side code

LCDS 2.5 brought a new assembler, SQLAssembler. SQLAssembler lets you connect your Flex client to your database. Usually, when you read/write data with LCDS, you create your own Java adapter to handle these operations. With SQLAssembler, instead of writing the Java code for accessing the database, you configure access to the database and write the SQL for read/write/delete directly into the data-management-config.xml file (this is a configuration file used by Flex data services). Basically, you write some simple XML with some SQL for each operation, and you don’t need to write a single line of Java. But, you get a full CRUD application, with all the benefits of Flex Data Services: collaboration, conflict resolution, paging. If you need for some operations to use stored procedure instead of SQL statements, there is no problem as SQLAssemberl has support for them.

Why should you use SQLAssembler?

I will not try to fool you. Probably it isn’t good for complex applications, where you have a lot of business logic on your server. But, it could come in very handy when you need to create a simple application, maybe a quick prototype for example. And the best thing is that if, for some reason, you decide that you need a custom assembler or HibernateAssembler instead of SQLAssembler, there should be little to change in the Flex client code, if anything at all. And, as you will see in this article, I can use this assembler to create a full CRUD application for one-to-many relationship database setup.

Prerequisites

In order to be able to follow this article and to try the attached project, you need to have: Flex Builder 3, WTP (Web Tool Project) installed in Flex Builder, and LCDS 2.5 or newer. If you don’t have Flex Builder, you can download a trial from here; if you don’t have WTP installed, then check my article here; finally if you don’t have LCDS, you can download it from here. I use a combined Flex and Java project with LCDS. I have explained this kind of setup here. Finally you need to have Tomcat 5.5 installed (I created my project using Tomcat as a server for WTP deployment).

You can download the project from here (it is a pretty big download, so be patient) and you can import it in Flex Builder, using the Import Flex Builder wizard.

Finally, in the root of the project, there is a database.sql file you can use it to create the database. In my project, I used MySQL as a database server.

Database structure

The database structure is very simple: two tables, one for storing the authors and one for storing the books. One author can have as many books as needed:

sqla_db_structure

Application description

I want to create a Flex application that lets me edit these two tables (full CRUD). I want to be able to choose an author, and see what books he wrote. This is the layout of the application (I know it isn’t a beautiful one, but that’s not the point of this article :D ).

sqla_app

When you work with Flex data services and LCDS, a common first step in creating the application is to configure the destinations using the data-management-config.xml file. You can find this file under the “WebContent/WEB-INF/flex/” folder. Here is the content of my file:

<?xml version="1.0" encoding="UTF-8"?>
<service id="data-service" class="flex.data.DataService">

    <adapters>
        <adapter-definition id="actionscript" class="flex.data.adapters.ASObjectAdapter" default="true"/>
        <adapter-definition id="java-dao" class="flex.data.adapters.JavaAdapter"/>
    </adapters>

    <default-channels>
       <channel ref="my-rtmp"/>
       </default-channels>    

    <destination id="sql-author">
        <adapter ref="java-dao"/>
            <properties>
                <use-transactions>true</use-transactions>
                <source>flex.data.assemblers.SQLAssembler</source>
                <scope>application</scope>
                <metadata>
                    <identity property="id_aut"/>
                </metadata>
                <server>
                    <database>
                        <!-- Example for HSQL DB:
                        <driver-class>org.hsqldb.jdbcDriver</driver-class>
                        <url>jdbc:hsqldb:hsql://myserver:9002/flexdemodb</url>-->
                        <driver-class>com.mysql.jdbc.Driver</driver-class>
                        <!-- Modify the URL below with the actual location of the flex360 database on your system -->
                        <url>jdbc:mysql://localhost/flex360</url>
                        <username>root</username>
                        <password>insfarsit</password>
                        <login-timeout>15</login-timeout>
                    </database>
                    <!-- Use this syntax when using a JNDI data source-->
                    <!--
                    <database>
                    <datasource>java:comp/env/jdbc/flexdemodb</datasource>
                    </database>
                    -->
                    <actionscript-class>com.flex360.VOAuthor</actionscript-class>
                    <fill>
                        <name>all</name>
                        <sql>SELECT * FROM authors_aut ORDER BY fname_aut</sql>
                    </fill>
                    <get-item>
                        <sql>SELECT * FROM authors_aut WHERE id_aut = #id_aut#</sql>
                    </get-item>
                    <create-item>
                        <sql>INSERT INTO authors_aut (fname_aut, lname_aut) VALUES (#fname_aut#, #lname_aut#)</sql>
                        <id-query>SELECT LAST_INSERT_ID()</id-query> <!-- MySQL syntax to    retrieve value of autoincremented column -->
                    </create-item>
                    <update-item>
                        <sql>UPDATE authors_aut SET fname_aut=#fname_aut#, lname_aut=#lname_aut# WHERE id_aut=#_PREV.id_aut#</sql>
                    </update-item>
                    <delete-item>
                        <sql>DELETE FROM authors_aut WHERE id_aut=#id_aut#</sql>
                    </delete-item>
                    <count>
                        <name>all</name>
                        <sql>SELECT count(*) FROM authors_aut</sql>
                    </count>
                </server>
            </properties>
    </destination>

    <destination id="sql-book">
        <adapter ref="java-dao"/>
            <properties>
                <use-transactions>true</use-transactions>
                <source>flex.data.assemblers.SQLAssembler</source>
                <scope>application</scope>
                <metadata>
                    <identity property="id_boo"/>
                </metadata>
                <server>
                    <database>
                        <driver-class>com.mysql.jdbc.Driver</driver-class>
                        <!-- Modify the URL below with the actual location of the flexdemodb database on your system -->
                        <url>jdbc:mysql://localhost/flex360</url>
                        <username>root</username>
                        <password>insfarsit</password>
                        <login-timeout>15</login-timeout>
                    </database>
                    <actionscript-class>com.flex360.VOBook</actionscript-class>
                    <fill>
                        <name>all</name>
                        <sql>SELECT * FROM books_boo ORDER BY title_boo</sql>
                    </fill>
                    <fill>
                        <name>byAuthorID</name>
                        <sql>SELECT * FROM books_boo WHERE idaut_boo = #id_aut# ORDER BY title_boo</sql>
                    </fill>
                    <get-item>
                        <sql>SELECT * FROM books_boo WHERE id_boo = #id_boo#</sql>
                    </get-item>
                    <create-item>
                        <sql>INSERT INTO books_boo (idaut_boo , title_boo, description_boo) VALUES (#idaut_boo#, #title_boo#, #description_boo#)</sql>
                        <id-query>SELECT LAST_INSERT_ID()</id-query> <!-- MySQL syntax to    retrieve value of autoincremented column -->
                    </create-item>
                    <update-item>
                        <sql>UPDATE books_boo SET idaut_boo=#idaut_boo#, title_boo=#title_boo# , description_boo=#description_boo# WHERE id_boo=#_PREV.id_boo#</sql>
                    </update-item>
                    <delete-item>
                        <sql>DELETE FROM books_boo WHERE id_boo=#id_boo#</sql>
                    </delete-item>
                    <count>
                        <name>all</name>
                        <sql>SELECT count(*) FROM books_boo</sql>
                    </count>
                    <count>
                        <name>byAuthorID</name>
                        <sql>SELECT count(*) FROM books_boo WHERE idaut_boo = #id_aut#</sql>
                    </count>
                </server>
            </properties>
        </destination>
</service>

I will not explain each XML tag of this file, as you can find a good description in the LCDS Developer Guide (page 183: Using SQL assembler). But, I want to highlight some of them. For example, I need to specify what adapter I want to use. Because I want to talk with a Java server, I use the Java Adapter:

<adapters>
    <adapter-definition id="java-dao" class="flex.data.adapters.JavaAdapter"/>
</adapters>

If I had wanted to create a data service transient, which does not store anything on the client, I could have used the ActionScript adapter. Or if I had wanted to use LCDS with ColdFusion, I could have used the ColdFusion adapter. Then, I set the default channel for communication between the Flex and server to RTMP (Real Time Message Protocol). This channel type maintains an open connection between the client and the server; as a result the client does not have to poll the server. I could also use the AMF channel (Action Message Format) with poll enabling. LCDS 2.6 lets you define more then one channel, so the data service can change it for the best performance. For example, the RTMP channel cannot be used if firewalls are in place, but LCDS can use a channel over HTTP in this case AMF.

<default-channels>
   <channel ref="my-rtmp"/>
</default-channels>

Finally, I define my two destinations, one for each database table. This code is pretty straight-forward: I define the source for the destination (flex.data.assemblers.SQLAssembler), then I define the property (this is the primary key field name of my table), then I configure the database access (I use MySQL, and just fill in the database driver, URL to database and user/password). Don’t forget to change these settings to match your database configuration. Usually, when you use data services, you want the destination to return to the Flex client ActionScript value objects. To do this all I need is to provide the fully qualified name of the ActionScript class I want to be used for wrapping a table record and, in Flex I need to create this class with the same fields name as the table and with the same data type.

<actionscript-class>com.flex360.VOAuthor</actionscript-class>

And now I am ready to define the SQL statements for these operations: fill, get item, create item, delete item and count:

<fill>
<name>all</name>
<sql>SELECT * FROM authors_aut ORDER BY fname_aut</sql>
</fill>
<get-item>
<sql>SELECT * FROM authors_aut WHERE id_aut = #id_aut#</sql>
</get-item>
<create-item>
<sql>INSERT INTO authors_aut (fname_aut, lname_aut) VALUES (#fname_aut#, #lname_aut#)</sql>
<id-query>SELECT LAST_INSERT_ID()</id-query> <!– MySQL syntax to retrieve value of autoincremented column –>
</create-item>
<update-item>
<sql>UPDATE authors_aut SET fname_aut=#fname_aut#, lname_aut=#lname_aut# WHERE id_aut=#_PREV.id_aut#</sql>
</update-item>
<delete-item>
<sql>DELETE FROM authors_aut WHERE id_aut=#id_aut#</sql>
</delete-item>
<count>
<name>all</name>
<sql>SELECT count(*) FROM authors_aut</sql>
</count>

You can define more SQL statements for the fill and count; for example, in my case, I want to be able to retrieve all the books or to retrieve all the books for a specific author. Thus I create two different fill methods, and I can use either one by using the name value.

<fill>
    <name>all</name>
    <sql>SELECT * FROM books_boo ORDER BY title_boo</sql>
</fill>
<fill>
    <name>byAuthorID</name>
    <sql>SELECT * FROM books_boo WHERE idaut_boo = #id_aut# ORDER BY title_boo</sql>
</fill>

When you need to reference in the SQL a value from the argument (for example, the second SQL for retrieving the books for an author, needs the author id), in Flex you pass the object as an argument when calling the data service operation, and in the data-management-config.xml file you use this notation to access a property from the object: #property name#. When you write the update or delete SQL statements, you need to reference the old values to write the condition. You can do this, using this syntax: UPDATE authors_aut … WHERE id_aut=#_PREV.id_aut# (_PREV gives you access to the values before the update).

Flex code

When you configure your Flex Java project to use Tomcat for deploying, you need to add “context.xml” file under “WebContent/META-INF/” folder, or you will get an error “Unable to access UserTransaction in DataService” when you try to save data.

<!-- Uncoment for Tomcat 5.5 (JDK 1.5 or newer) -->
<Context reloadable="true" privileged="true" antiResourceLocking="false" antiJARLocking="false">
    <Transaction factory="org.objectweb.jotm.UserTransactionFactory" jotm.timeout="60"/>
</Context>

Unable to access UserTransaction in DataService

And finally, it is always a good idea to enable logging on the LCDS server side when developing. In the “WebContent/WEB-INF/flex/services-config.xml” file I changed the value from Error to ALL:

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

With this, I am able to see in the console view from Eclipse, everything that is happening when I call my destinations:

Eclipse Console and LCDS log

Now I am really ready to start coding the application. First I lay down the UI for the application. In my mxml application file, lcds_java.mxml, I create two data grids and two forms for holding the data and editing it and also I create the bindings between the model and various UI components.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="initApp()">
<mx:Script source="author.as"/>
<mx:Script source="book.as"/>

<mx:VBox height="100%">

    <!-- buttons and data grid for authors -->
    <mx:HBox>
        <mx:Button label="Get authors" click="getAuthors()"/>
        <mx:Button label="New author" click="clickNewAuthor()"/>
    </mx:HBox>
    <mx:HBox>
        <mx:DataGrid id="dgAuthors" dataProvider="{authorsCollection}" click="editAuthor(event)">
            <mx:columns>
                <mx:DataGridColumn headerText="ID" dataField="id_aut" width="30"/>
                <mx:DataGridColumn headerText="First Name" dataField="fname_aut"/>
                <mx:DataGridColumn headerText="Last Name" dataField="lname_aut"/>
            </mx:columns>
        </mx:DataGrid>
        <!-- form for author -->
        <mx:Form>
            <mx:FormItem label="First name:">
                <mx:TextInput id="txtFname" text="{author.fname_aut}"/>
            </mx:FormItem>
            <mx:FormItem label="Last name:">
                <mx:TextInput id="txtLname" text="{author.lname_aut}"/>
            </mx:FormItem>
            <mx:FormItem horizontalAlign="right">
                <mx:HBox>
                    <mx:Button label="Save" click="saveAuthor()" id="btnNewAuthor" enabled="false"/>
                    <mx:Button label="Delete" click="deleteAuthor()" id="btnDeleteAuthor" enabled="false"/>
                </mx:HBox>
            </mx:FormItem>
        </mx:Form>
    </mx:HBox>

    <mx:Spacer height="25"/>

    <!-- buttons and data grid for books -->
    <mx:HBox>
        <mx:Button label="Get books for selected author" click="getBooksForAuthor()" y="+10"/>
        <mx:Button label="New book" click="clickNewBook()"/>
    </mx:HBox>
    <mx:DataGrid id="dgBooks" dataProvider="{booksCollection}" click="editBook(event)">
        <mx:columns>
            <mx:DataGridColumn headerText="ID" dataField="id_boo" width="30"/>
            <mx:DataGridColumn headerText="A. ID" dataField="idaut_boo" width="40"/>
            <mx:DataGridColumn headerText="Title" dataField="title_boo" width="190"/>
            <mx:DataGridColumn headerText="Description" dataField="description_boo" dataTipField="description_boo" width="300"/>
        </mx:columns>
    </mx:DataGrid>

    <!-- form for book -->
    <mx:Form>
        <mx:FormItem label="Author:">
            <mx:ComboBox id="comboAuthor" dataProvider="{authorsCollection}" labelFunction="getAuthorName"/>
        </mx:FormItem>
        <mx:FormItem label="Title:">
            <mx:TextInput id="txtTitle" text="{book.title_boo}"/>
        </mx:FormItem>
        <mx:FormItem label="Description:">
            <mx:TextInput id="txtDescription" text="{book.description_boo}"/>
        </mx:FormItem>
        <mx:FormItem horizontalAlign="right">
            <mx:HBox>
                <mx:Button label="Save" click="saveBook()" id="btnSaveBook" enabled="false"/>
                <mx:Button label="Delete" click="deleteBook()" id="btnDeleteBook" enabled="false"/>
            </mx:HBox>
        </mx:FormItem>
    </mx:Form>
</mx:VBox>

<!-- Bindings for author form to author object -->
<mx:Binding destination="author.fname_aut" source="txtFname.text" />
<mx:Binding destination="author.lname_aut" source="txtLname.text" />
<!-- Bindings for book form to book object -->
<mx:Binding destination="book.idaut_boo" source="VOAuthor(comboAuthor.selectedItem).id_aut" />
<mx:Binding destination="book.title_boo" source="txtTitle.text" />
<mx:Binding destination="book.description_boo" source="txtDescription.text" />    

</mx:Application>

I put the code to wire up this UI into ActionScript files: “author.as” and “book.as”. There are two ActionScript classes for storing one record for each table:

package com.flex360 {
    import mx.collections.ArrayCollection;

    [Managed]
    [RemoteClass]
    public class VOAuthor     {

        public var id_aut:int;
        public var fname_aut:String;
        public var lname_aut:String;
    }
}
package com.flex360 {

    [Managed]
    [RemoteClass]
    public class VOBook {

        public var id_boo:int;
        public var idaut_boo:int;
        public var title_boo:String;
        public var description_boo:String;
    }
}

Usually, after the RemoteClass metadata, you write the Java class counterpart, something like this: [RemoteClass(alias=”com.flex360″)]. In the case of SQLAssembler, you don’t need this. If you try to give an alias you will get this error:

TypeError #1034: Type Coercion failed

If you try to add java-class to the destination definition, for example something like this:

<actionscript-class>com.flex360.VOAuthor</actionscript-class>
<java-class>com.flex360.VOAuthor</java-class>

when you start the server you will see this error in the console:

[Flex] Error instantiating application scoped instance of type 'flex.data.assemblers.SQLAssembler' for destination 'sql-author'.
flex.data.adapters.AdapterException: Only one of java-class or actionscript-class may be set for destination 'sql-author'.
    at flex.data.assemblers.SQLAssembler.initialize(SQLAssembler.java:130)
    at flex.messaging.factories.JavaFactoryInstance.createInstance(JavaFactoryInstance.java:99)
    at flex.messaging.factories.JavaFactory.createFactoryInstance(JavaFactory.java:113)
    at flex.messaging.FactoryDestination.createFactoryInstance(FactoryDestination.java:252)
    at flex.messaging.FactoryDestination.getFactoryInstance(FactoryDestination.java:235)
    at flex.messaging.FactoryDestination.getFactoryInstance(FactoryDestination.java:223)
    at flex.data.DataDestination.getFactoryInstance(DataDestination.java:317)
    at flex.data.adapters.JavaAdapter.initialize(JavaAdapter.java:185)
    at flex.messaging.config.MessagingConfiguration.createAdapter(MessagingConfiguration.java:365)
    at flex.messaging.config.MessagingConfiguration.createDestination(MessagingConfiguration.java:352)
    at flex.messaging.config.MessagingConfiguration.createServices(MessagingConfiguration.java:320)
    at flex.messaging.config.MessagingConfiguration.configureBroker(MessagingConfiguration.java:100)
    at flex.messaging.MessageBrokerServlet.init(MessageBrokerServlet.java:126)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1105)
    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:932)
    at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:3951)
    at org.apache.catalina.core.StandardContext.start(StandardContext.java:4225)
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1013)
    at org.apache.catalina.core.StandardHost.start(StandardHost.java:718)
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1013)
    at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:442)
    at org.apache.catalina.core.StandardService.start(StandardService.java:450)
    at org.apache.catalina.core.StandardServer.start(StandardServer.java:709)
    at org.apache.catalina.startup.Catalina.start(Catalina.java:551)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:294)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:432)

SQLAssembler does not support hierarchical data. This means I need to take care of the dependencies myself, for example when an author is deleted, I need to ensure all his books are deleted (HibernateAssembler, on the other hand, supports this). So this means I will have more code to write. I will not discuss each line of code, as you can download the project and see the commented ActionScript code, but I will explain at a high level how I implemented it.

When working with Flex Data Services, you basically deal with a managed collection and all the operations for change, add, delete are on this collection. If you compare it with the same CRUD operations implemented over a SOAP or REST or RPC service, it is slightly different – each operation is implemented as a call to the server, so you can say it is method centric, where in the case of the data services, you deal with the collection, so you can say it is data centric.

For my application, I need two ArrayCollections, one for each table. These two collections will be managed by one data service, again one for each table. Each collection will be filled with Value Objects: the authors collection with VOAuthor, and the books collection with VOBook. The form for editing an author is bound to an author variable of type VOAuthor, and the form for editing a book is bound to a book variable of type VOBook. When I click on a row from the authors data grid, I set the author variable to point to the selected author from the authors collection. The same goes for the books form. Here are these six variables:

/**
 * DataService for Author destination
 */
private var authorDS:DataService;
/**
 * DataService for Book destination
 */
private var bookDS:DataService;
/**
 * Authors collection
 */
[Bindable]
private var authorsCollection:ArrayCollection = new ArrayCollection();
/**
 * Books collection
 */
[Bindable]
private var booksCollection:ArrayCollection = new ArrayCollection();
/**
 * Author object to use for populating the edit form for authors
 */
[Bindable]
private var author:VOAuthor = new VOAuthor();
/**
 * Book object to use for populating the edit form for books
 */
[Bindable]
private var book:VOBook = new VOBook();

As I’ve already said, SQLAssembler does not manage relationships for me (I have a one-to-many relation in my application). Thus, whenever an author is selected in the authors data grid, I call the fill method for the books dataservice and I retrieve only the books for this author. And when an author is deleted, I need to take care to delete his books as well (to do this I make sure I fill the books collection with the current author’s books and then I delete the author and each book from the books collection). For more, please download the project and take a look at the code. You will find plenty of comments.

And because I use data service, I have also data push built in in my application. For example, when someone changes an author, my data are updated automatically (in the right browser I added a new author, Mihai Corlan, and the left browser automatically displayed the change):

Data push

And if more than one person is editing the same piece of the information, you have conflict resolution support (I submitted the changes in the right browser while I was editing the same author in the left browser; so I get an message to inform me that a conflict was detected and the values from the server will be kept):

Flex Data service Conflict Detection

Final words

That’s it folks! I am still working on the paging feature for SQLAssembler, as well on extending the SQLAssembler. As soon as I nail down these challenges, I will post an update.

29 thoughts on “SQLAssembler: create a Flex and Java application with LCDS (LiveCycle Data Services) without server side code

  1. Thanks for this nice post. I am not able to download the project, can you please upload it.

    Thanks.

  2. @shaheer

    Yeap, it had an extra char. Now it should work.
    Thanks for the nice words and for the telling me about the broken link :)

  3. Beta expired problem with the lcds (or blazeds) libraries used in your project. After remplacing by new libraries of blazeds :

    **** MessageBrokerServlet failed to initialize due to runtime exception: flex.messaging.MessageException: Cannot create class of type ‘flex.messaging.endpoints.RTMPEndpoint’. Type ‘flex.messaging.endpoints.RTMPEndpoint’ not found.

  4. Oups, sorry, in fact I really don’t find flex.messaging.endpoints.RTMPEndpoint anywhere…

  5. @Erwan Baynaud

    Hi,

    Indeed, the beta 2 I used it has expired. I uploaded a new archive of the project that is using the release version of LCDS and you should’t have any problem.

    By the way, SQLAssembler needs LCDS and not BlazeDS :)

    Anyway, please let me know if it worked!

    thanks for your comments :)

  6. Here is the first bad message in my console:

    [Flex] Adobe Livecycle Data Services: 2.6.0.196815 Express: beta license expired!
    [Flex] MessageBroker failed to start: flex.messaging.license.InvalidLicenseException: Beta expired.

    But this is with blazeds… I can’t find a simple LCDS on Adobe website : http://www.adobe.com/products/livecycle/dataservices/
    This has changed since yesterday I think !

    I don’t really understand what are these licence issues… But I want to succeed with this SqlAssembler !!!

  7. Not better :

    Flex] MessageBroker id: __default__ classLoader is: the MessageBroker’s class loader and the context class loader (classLoader hashCode: 20079748 (parent hashCode: 21061094 (parent hashCode: 8116722 (parent system)))
    [Flex] MessageBroker failed to start: flex.messaging.license.InvalidLicenseException: An invalid license key was entered. To enable Adobe Flex Data Services Express, which does not require a license, please remove the invalid license key from license.properties.
    at flex.messaging.license.LicenseServiceImpl.validateLicense(LicenseServiceImpl.java:348)
    at flex.messaging.license.LicenseServiceImpl.init(LicenseServiceImpl.java:390)
    etc…

    I don’t understand this problem of licence.

  8. Oups, that was when I try to put a key in licence.properties. The message with your project without any change is:

    [Flex] MessageBroker id: __default__ classLoader is: the MessageBroker’s class loader and the context class loader (classLoader hashCode: 1321194 (parent hashCode: 21061094 (parent hashCode: 8116722 (parent system)))
    [Flex] Adobe Livecycle Data Services: 2.6.0.196815 Express: beta license expired!
    [Flex] MessageBroker failed to start: flex.messaging.license.InvalidLicenseException: Beta expired.
    at flex.messaging.license.LicenseServiceImpl.init(LicenseServiceImpl.java:400)

  9. @Erwan Baynaud

    I tried the new zip I uploaded for this post on other computer and it worked without any problem. The error you are seeing make me think that it is possible to work with the same old sample code. Are you sure you deployed the new code?

  10. Don’t worry, this is ok now. The example in LCDS ditribution of SqlAssembler is functionning well. I think my environnement was not perfect: some configuration elements were missing.

    One question although: If we decide to delete manually an element in the mysql database (with mysql query browser for instance), is it automatically rendered in the fles application ? Is is a feature of LCDS ?

  11. No, you need to delete the row from within a LCDS Data Service. There is no way the LCDS to catch these changes at the database level.

  12. And is it possible to delete all the rows of a table ? And is it possible to create some personalized sql requests ?

  13. I will look into this; my guess if it is possible, then it is by extending the SQLAssembler class. But it seems that although it supposed to be included the source in the LCDS distribution, in fact it isn’t (I was able to find only the HibernateAssembler).

  14. Erwan,

    You can create a trigger and use JMS in order to notify LCDS about changes (rows deleted, inserted, updated). It should work if you are using DB2 or Oracle but I do not know if you can do that when using MySQL.

  15. Question–does anyone know if its best practice to create a combined WTP, livecycle tools project or keep them separated?

  16. Hi Heather,

    I don’t know if this choice is about best practices or more about personal preferences. For example some people from our team prefer to work with combined WTP / Flex projects, others don’t. I think the best thing is to try both approaches and decide yourself which one works the best for you.

  17. Hi,
    i want to upload and download image,video,document files like .doc,.pdf,.zip etc with flex and lcds. can u please help me regarding this.

    Thanks

  18. Hi i have a problem and i will be very pleased if you can help:

    i have an engine that is inserting data into a table and what i want is that the lcds to reflect the changes to the clients (so its not a client that is changing so that it can be reflected to other clients)

  19. @Joe

    Can you read the comment that Conel Creanga posted? It is answering to your question.

  20. I tried to make the example work with Oracle DB by changing data-management-config.xml.
    <!– SELECT LAST_INSERT_ID() MySQL syntax to retrieve value of autoincremented column –>
    SELECT author_id.nextval from dual
    Here author_id is a sequence created in Oracle DB,since it does not support autoincrement.
    The application is connecting to the db and retrieving the values by the query but,it not filling the collection.
    Output from console:
    [Service.Data.General] Null value for identity property: id_aut on instance of type: flex.messaging.io.amf.ASObject for destination: sql-author.

    DB table was changed to :
    create table AUTHORS_AUT
    (
    ID_AUT NUMBER(11) not null,
    FNAME_AUT VARCHAR2(255) not null,
    LNAME_AUT VARCHAR2(255)
    )

  21. Hi Michai,
    Is there any way to create destination defined in proxy-config.xml file dynamically.

    Our Flex Application uses LCDS to proxy Web Services. We used LCDS that integrated with ColdFusion 8 Server. Since we have several domains configurations: production, development ext…
    For every domain we used different wsdl and soap urls, so we need to setup proxy-config.xml on each server domain manually.

    It would be great, if I can some how create destinations defined in proxy-service.xml dynamically.
    I was trying to find any suggestion in LCDS Developers Guide, there you can find some bootstrap service example for datamanagement service, not sure can we used something like bootstrap service but for proxy-config.xml

    Thanks in advance for yours help
    Irene

  22. have two dataServices pointing to the same destination

    i got two buttons with a binding to the property text with the flag commitRequired for every DS

    and if i make a change in the list associated to dsCompany , there is a change in dsCompanyTwo.commitRequired too!!

    why happen this?

    Best regards

  23. I have downloaded the project, but when I run the projects displayed This error “The requested resource (/ lcds_java / lcds_java.html) is not available.” I have changed my connection database password, the other is Exactly the same,I use Flash builder 4 plug-in for windows,eclipse 3.5
    can you help me ?

  24. Pingback: harikrishnaflex

Leave a Reply

Your email address will not be published. Required fields are marked *