Using a MySQL Datasource with Tomcat and LCDS 3.0

I’ve spent today becoming familiar with LiveCycle Data Services 3.0 and am excited by the direction the product is going in. You’re going to hear a lot more about model driven development from us and I think LCDS 3.0 is a product that 1) makes full use of the Flash Platform and Flex’s capabilities and 2) shows what it takes to build a genuine rich Internet application.

One issue I ran into though was getting a MySQL database to work with the Tomcat installation of LCDS 3.0 so I wanted to quickly blog the steps I went through. The instructions here were hugely helpful and I wanted to break them down for an LCDS-specific install of Tomcat

  • First you need to get the MySQL drivers for Java which are available here. As of this post the most recent drivers are version 5.1.
  • Copy the mysql-connector-java-5.1.8-bin.jar file into the lib/ directory of your tomcat install (/Applications/lcds/tomcat/ by default).

Once that's copied, open the xml file for your specific server inside of the tomcat/conf/Catalina/localhost/ directory. In this case, I'm using the default lcds server, so I need to change lcds.xml. You'll also see the other servers that come with LCDS 3.0 like lcds-samples.xml and ds-console.xml.

Copy this code into that file anywhere inside the Context tags and replace {databaseName} with the name of your database, and change the other {} variables accordingly.

    <Resource name="jdbc/{databaseName}" type="javax.sql.DataSource"
          driverClassName="com.mysql.jdbc.Driver"
          url="jdbc:mysql://{host}:{databasePort}/{databaseName}"
          username="{username}" password="{password}" />

Now you're all set! Once you've got RDS set up on your LCDS 3.0 server you'll be able to see the MySQL database and start using it for your model driven development.

Upcoming Presentations in Portland and San Jose

After a couple of months at home coding, emailing, and getting my blog back on, I’m going out on the road again. I’ll be in Portland for OSCON next week and I’m also going to be presenting Online/Offline Synchronization with Adobe AIR and LiveCycle Data Services to PDXRIA on Thursday. I thought I was also going to be giving this talk tonight to the Austin Flex User Group but it turns out I was off by a day and I missed it. Sorry guys!

In August I’ll be heading down to 360Flex, the premiere Flex conference, to give the same talk (but probably more polished). The talk is primarily targeted at developers who want to take a look at how to start taking AIR applications offline and having a server do all the work. I’ve been coding demos and examples the past couple of weeks and it is really, really impressive how easy it is. I hope to see you at one of those conferences!

Using LiveCycle Data Services 2.6 Inside of ColdFusion 8

By default, ColdFusion 8 comes with LCDS 2.5. But there’s a lot of new, good stuff in LCDS 2.6 that might be good to take advantage of if you’re doing data services work in ColdFusion. There are some instructions on Labs, but I just tried them tonight, and I think they’re terrible. Luckily, Joshua Rodgers has a great step-by-step walkthrough for getting LCDS 2.6 up and running inside your ColdFusion 8 server.

I just wanted to make sure people saw Joshua’s instructions and didn’t waste time like I did decoding the official version.

Online/Offline Synchronization with Adobe AIR

One of the biggest problems I think we have when dealing with the offline/online problem is synchronization. Doing conflict resolution for data when you get back online is a big pain in the ass. With AIR, more Adobe developers are starting to think about the problem and luckily we have a good solution with LiveCycle Data Services 2.6. I’m going to be talking about Online/Offline Synchronizaton with AIR and LCDS at 360|Flex San Jose, but Christophe Coenraets just published a wicked example of how it works called InSync. Well worth checking out.

Real Time Communication with Flex and AIR using ColdFusion and LiveCycle Data Services

In this walkthrough I’m going to take you through using ColdFusion (which contains LiveCycle Data Services) to create real time communication between an application in the browser and one on the desktop built with Adobe AIR. Both applications are written in Flex. You’ll see how we can create a better user experience on the desktop by using things like drag-and-drop and still tie that into a real time scenario inside of the browser.

The first thing you need to do is get ColdFusion 8 or LiveCycle Data Services (LCDS). For this tutorial I’m using RTMP which BlazeDS doesn’t support. I’ll have a BlazeDS example out later this week hopefully. ColdFusion has a LiveCycle Data Services install on top of it, so that’s what I’m going to use. You can grab all of the code from my SVN repository under the GPXShare project. You’ll also need my AS3 GPX library. I’ve got a sample GPX file you can use as well.

The second thing to be aware of is there are two general categories of communication in LiveCycle DS: the real time communication using RTMP and data management. Data Management lets you do things like synchronize data between online and offline sources while real time communication allows you to push data to clients instead of having to force clients to check in with a server. Data management is included in LiveCycle DS but not Blaze DS and BlazeDS doesn’t support the RTMP protocol but does have support for AMF for psuedo-real time communication. For this I’m just talking about real time messaging over RTMP. Damon Cooper has a good blog post about the differences between RTMP and AMF and how they apply to BlazeDS and LiveCycle DS.

The code is really, really simple. In my example, called GPXShare, I have two applications, one is a Flex-based application running in the browser and the other is a Flex-based AIR application on the desktop. You’ll see that I’m reusing a lot of code, one of the great things about using Flex is that you can quickly and easily move between the browser and the desktop. What I’m going to do is take an XML file with a bunch of GPS waypoints, drag it on to my AIR application, which will then send out that data to the browser application. You can have any number of browser applications open – each one “subscribes” to messages coming from the AIR application so they get the data in real time. The second part adds a tiny bit of collaboration. I want to be able to select a specific waypoint in either the AIR version or the Flex browser version and have that selection be highlighted on all the clients. All of that is really easy to do with LiveCycle Data Services.

Let’s first take a look at the AIR application. In my AIR app I have two pieces of code which establish a Producer and Consumer:

<mx:Producer id="producer" destination="GpxShare" />
<mx:Consumer id="consumer" destination="GpxShare"
			    message="doMessage( event );" />

. The Producer lets me send code out and the Consumer is what watches for changes. Each of those point to a destination which tells all of the connected clients how to pass the information back and forth. There are a couple of things we need to configure on the server now that we’ve seen the consumer and the producer.

  • The Destination – The first thing is to set the destination. We’re looking for a file called messaging-config.xml in the /WEB-INF/flex/ directory. In ColdFusion it’s located in your wwwroot directory. Add the following code in between the <adapters> node:
    <destination id="GpxShare">
    	<adapter ref="actionscript" />
    	<channels>
    		<channel ref="cf-rtmp" />
    	</channels>
    </destination>
    
  • The Channel – Now that we’ve set the destination, he second thing we need is to make sure that “cf-rtmp” channel exists. The channel tells the connected clients which protocol they’re all using to get to each other and where to send the information. Here we’re looking for a file called services-config.xml which will be in the same place as the destination config file. Once you find it, the channel definition should already be there you just need to uncomment it and tweak it. It should look like this:
    <channel-definition id="cf-rtmp"
    	class="mx.messaging.channels.RTMPChannel">
    <endpoint uri="rtmp://localhost:2048"
    	class="flex.messaging.endpoints.RTMPEndpoint"/>
    <properties>
             <idle-timeout-minutes>20</idle-timeout-minutes>
                  <serialization>
                      <instantiate-types>false</instantiate-types>
                  </serialization>
              </properties>
    </channel-definition>
    

So we’ve got our configuration files set up (you’ll have to rebuild your Flex project if you’re following along at home to make sure they get the new configuration settings). With that Producer/Consumer tag set up in our AIR application we’re ready to send out some data. Using the AIR API’s I’ve enabled drag and drop events from the file system so that when I drag in a GPX file, it will parse the data and display it in the grid. Once that happens we use the Producer to send the data out to all of our consumers with a doSend() function:

// Send our changes out to the consumers
public function doSend( array : Array ):void
{
	// Create the message and set the message body to our data
	var mess:AsyncMessage = new AsyncMessage();
	       mess.body.waypoints = array;
	       producer.send( mess );
}

The doSend() function is called after we finish opening the file from the file system and we just pass in the array of Waypoints. We create a new asynchronous message for storing our data and then set the body of that message to our data. In this case I’m sending an array with the name of waypoints. Finally we call the send() method on our Producer to fire it off. Now lets take a look at what happens inside of our browser application.

If you take a look at the code, you can see that we get to reuse a lot. Same data grid code and the same Producer/Consumer code. In this case, the browser is acting as a Consumer and you can see we’ve set the message attribute: message="doMessage( event );". This sets all of the consumers to watch for new messages and when they come in to call that doMessage function. So when we get message from our Consumer (the AIR application) with new GPS data, we call doMessage() in the browser:

// This is what happens when we get a message from the producer
public function doMessage( event:MessageEvent ):void
{
	// Logic checks to see which kind of message we're getting
	if( event.message.body.waypoints != null )
	{
	   dg.dataProvider = event.message.body.waypoints as Array;
	}
	dg.selectedIndex = event.message.body.selectedIndex;
}

Pretty straight forward. We’re passing in a MessageEvent and that MessageEvent contains the waypoint array we passed in from the AIR application. The only semi-tricky thing is that because this application also sends the selected row information back and forth, I do a check to make sure we actually have waypoint data and not just a new selected row number.

So that’s it! The only other part to the application is sending the selected row back and forth. For that you can again reuse a lot of the same code between the AIR application and the browser application. In both applications we follow the same steps. Set up a change event to fire on our data grid when we select a new row which calls a doChangeSend() function. Then attach the selectedIndex to the message body and pass it through the AsyncMessage. Now when we receive that message we set the selectedIndex of our data grid:

// When we make a change to the datagrid we
// send a message with this function
public function doChangeSend( event : ListEvent ) : void
{
	// Create the message and set the message body to our data
	var mess:AsyncMessage = new AsyncMessage();
	       mess.body.selectedIndex = dg.selectedIndex;
	       producer.send( mess );
}
// When we get back a change event
// make sure the right index is selected
public function doMessage( event:MessageEvent ):void
{
	dg.selectedIndex = event.message.body.selectedIndex;
}

That’s all there is to it. Remember you can grab the source code for both the browser-based Flex application and the desktop-based Flex application built with Adobe AIR from my SVN repository. If you have any question, leave a comment or send me an email. Damon Cooper also has a great list of resources for BlazeDS and LiveCycle Data Services for more information.