Saturnboy
 2.17
Code
off

I just wrote about how to handle special characters in Flex 4 when written as HTML entities in MXML. Now I’ve moved my data with the special characters out of MXML and down into a MySQL database. Data access is provided by a vanilla LCDS 3 backend. I now have a very different problem than what I had before: How do I get UTF-8 data out of the database with LCDS and onto the display?

MySQL and UTF-8

In theory, LCDS is perfectly happy with special characters and foreign languages (here’s a link to supported characters sets in LiveCycle ES2). So this time around, our problem has nothing to do with Flex 4 or LCDS, instead it’s all about the database. For our example, we’ll skip the pure model driven development route and just start with a simple database with a single players table.

Create the database:

CREATE DATABASE ballerz DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE USER 'baller'@'localhost' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON ballerz.* TO baller@localhost;

It is possible to configure MySQL to default to UTF-8 friendly behavior but the CREATE DATABASE command guarantees that the newly created db will be happy.

Create the players table:

CREATE TABLE players (
  id INT(11) NOT NULL AUTO_INCREMENT,
  name VARCHAR(255),
  PRIMARY KEY (id)
);

Nothing special here, just use VARCHAR for the text fields. In this case, we only have the player’s name.

Insert some sample data:

INSERT INTO players (id,name) VALUES (1, "Carmelo Anthony");
INSERT INTO players (id,name) VALUES (2, "Chaunçey Billups");
INSERT INTO players (id,name) VALUES (3, "Nenê");
INSERT INTO players (id,name) VALUES (4, "Këñÿõn Martin");
INSERT INTO players (id,name) VALUES (5, "LeBrøn James");
INSERT INTO players (id,name) VALUES (6, "Mo Williams");
INSERT INTO players (id,name) VALUES (7, "Shaquille O†Neal");
INSERT INTO players (id,name) VALUES (8, "Ænderson Varejao");
INSERT INTO players (id,name) VALUES (9, "Zýdrunãs Ílgauskãs");

I put some extra special characters into the INSERT statements just for fun.

Digging Deeper: When connecting to MySQL from the commandline you can use the --default-character-set=utf8 option to force your terminal to show UTF-8 characters correctly.

LCDS and UTF-8

Now that the database is correctly setup to handle UTF-8, the rest of the LCDS setup is straight forward (see my getting started part 1 and part 2 posts). Create a new LCDS webapp via copy-and-paste from the template app, then fire up Flash Builder 4 and get to work. In the Modeler plugin, configure a new RDS connection and just drag-and-drop the players table into the model.

Here’s a screenshot of our LCDS model:

model

And here’s a screenshot of the running app (remember this is backed by LCDS, so no running demo):

screenshot

Lastly, the frontend code showing just the highlights:

<?xml version="1.0" encoding="utf-8"?>
<s:Application ...
        creationComplete="complete()">
 
    <fx:Script>
        <![CDATA[
           private function complete():void {
                getPlayers.token = playerService.getAll();
            }
        ]]>
    </fx:Script>
 
    <fx:Declarations>
        <s:CallResponder id="getPlayers" />
        <Ballerz:PlayerService id="playerService" />
    </fx:Declarations>
 
    <s:List 
            dataProvider="{getPlayers.lastResult}"
            labelField="name" />
</s:Application>

Again, no magic here, I use a simple getAll() query to retrieve the entire players table then feed it into a List via the CallResponder‘s lastResult property.

Conclusion

So the moral of our story is: if you correctly configure your database to support UTF-8 and you correctly get UTF-8 data into your tables, then everything just works. LCDS will transparently get data out of the db and Flex will transparently get it onto the screen.

Files

 12.18

Once upon a time, in what now seems to be a prior life, I became a published author when my thesis hit the university press. That time has come again. After much effort, the second longest thing I have ever written has been published by InsideRIA. I wrote a two-part article titled Getting Real with LCDS 3 (Part 1 & Part 2) that covers the basics of model driven development with LCDS 3. Yeah me.

More Fun with LCDS

Since I’m such a new-stuff-loving guy I can’t help but return to the backend after a few months on the frontend with various Axiis visualizations (here & here) and a GTween animation (here). So, it’s back to LCDS. Of course, since I last wrote about LCDS, Adobe has shipped LCDS 3, but thankfully they still provide a free developer trial. This time around, I’ll look at LCDS and MySQL Views.

Create Database and Tables

First, let’s set the scene by constructing a new database and some tables. Here’s the database:

CREATE DATABASE football;
CREATE USER 'baller'@'localhost' IDENTIFIED BY 'password';
GRANT ALL PRIVILEGES ON football.* TO baller@localhost;

And here are the tables:

CREATE TABLE teams (
  id INT(11) NOT NULL AUTO_INCREMENT,
  name VARCHAR(255),
  PRIMARY KEY (id)
);
 
CREATE TABLE players (
  id INT(11) NOT NULL AUTO_INCREMENT,
  name VARCHAR(255),
  salary INT(11),
  team_id INT(11),
  PRIMARY KEY (id)
);
 
CREATE TABLE games (
  id INT(11) NOT NULL AUTO_INCREMENT,
  team_id INT(11),
  opp_id INT(11),
  points INT(11),
  win tinyint(1),
  PRIMARY KEY (id)
);

Lastly, we insert some sample data into the database via a script. The final result is our familiar teams-and-players database, but this time with an additional games table.

MySQL Views

A database view is one way to push logic and computations down from the application layer into the database. A judicious use of views can really help keep the application layer nice and clean. But much like database de-normalization, adding views to the database often feels like premature optimization, so be careful. LCDS and the Modeler plugin treat database views just like tables, so everything just works (sort of).

MySQL is a full-featured database that provides a simple CREATE VIEW syntax. For our purposes, a view can be thought of as nothing more than another table that is constructed from other tables via a SELECT statement. Because of this, database views are sometimes called virtual tables. The SELECT statement used to construct the view is often very complicated, involving multiple tables, joins, functions, expressions, and more.

For our example, we will construct two views. First, the team_summary view packages up information from the teams and players tables:

CREATE VIEW team_summary AS SELECT
  t.id,
  t.name,
  COUNT(p.id) AS num_players,
  ROUND(SUM(p.salary)/1000000,2) AS payroll,
  ROUND(AVG(p.salary), 0) AS avg_salary,
  MIN(p.salary) AS lowest_salary,
  MAX(p.salary) AS highest_salary
FROM teams AS t, players AS p WHERE t.id = p.team_id GROUP BY t.id;

The CREATE VIEW above joins the teams and players tables to create seven columns. Here’s a brief description of the generated columns:


 id
team id directly from teams table

 name
team name directly from teams table

 num_players
count up all player ids

 payroll
sum all player salaries

 avg_salary
average all player salaries

 highest_salary
find the maximum player salary

 lowest_salary
find the minimum player salary

Next, we create the game_summary view to collect data from the teams and games tables:

CREATE VIEW game_summary AS SELECT
  t.id,
  t.name,
  CAST(CONCAT(SUM(g.win), '-', COUNT(g.id) - SUM(g.win)) AS CHAR) AS record,
  CAST(SUM(g.points) AS SIGNED) AS points_for
FROM teams AS t, games AS g WHERE t.id = g.team_id GROUP BY t.id;

And a brief description of the generated columns:


 id
team id directly from teams table

 name
team name directly from teams table

 record
concatenate number of wins with number of losses (computed via total games minus wins)

 points_for
sum up all the team’s points for all games

Digging Deeper: The CAST statements are not necessary to construct the game_summary view as far as MySQL is concerned, but I need them to force the correct column types to make LCDS happy.

LCDS 3 and the Modeler Plugin

Now that our database is happily configured, fire up Flash Builder 4 and switch to the Modeler plugin. Create and configure a new LCDS webapp, and then take a look at the RDS Dataview panel:

rds-dataview

You can see both views and tables. Next, simply drag whatever tables or views you want over to the Modeler. Here’s the final model for our sample application:

model
LCDS Modeler Tricks & Tips

There are a couple of tricks to getting views working correctly in LCDS:

  1. Mark each view entity as persistent in the Properties panel (in theory, views can support updates to only those columns that are one-to-one mapped to a table)
  2. Set the id column as the ID property (this is required because views don’t have primary keys, so you have to tell LCDS what to do)
  3. Verify that the database types have correctly come across to LCDS, if not add a CAST to the view column to force the correct type (see table below)

Here’s a simple table showing how the types move from the MySQL database to LCDS, and then from LCDS to PASOs (aka Plain old ActionScript Objects):


 MySQL
LCDS
PASOs

 int
int
int

 bigint
long
int

 decimal
double
Number

 varchar
string
String

Data

We can view the data in the database by using the RDS Query Viewer. Here is the team_summary data:

team-summary

And here is the game_summary data:

game-summary
The App

Alas, since this is an LCDS app, no running demo is possible. Here’s a screenshot instead, showing a selected team and the associated team & game summary data.

screenshot

Our sample app closely follows the plan I set forward in Getting Real with LCDS, Part 2. We define our services and associated CallResponder‘s in MXML, and event handlers in ActionScript.

Here is the relevant section of code showing the various event handlers:

private function teamChangeHandler():void {
	var teamId:int = list.selectedItem.id
	getTeamSummary.token = teamSummaryService.getById(teamId);
	getGameSummary.token = gameSummaryService.getById(teamId);
}
 
private function getTeamSummaryResult(event:ResultEvent):void {
	var summary:TeamSummary = (event.result as IList).getItemAt(0) as TeamSummary;
	numPlayers.text = summary.numPlayers.toString();
	payroll.text = cf2.format(summary.payroll) + ' million';
	avgSalary.text = cf.format(summary.avgSalary);
	lowestSalary.text = cf.format(summary.lowestSalary);
	highestSalary.text = cf.format(summary.highestSalary);
}
 
private function getGameSummaryResult(event:ResultEvent):void {
	var summary:GameSummary = (event.result as IList).getItemAt(0) as GameSummary;
	record.text = summary.record;
	pointsFor.text = summary.pointsFor.toString();
}

And here is the MXML Declarations block:

<fx:Declarations>
	<s:CallResponder id="getAllTeams" />
	<s:CallResponder id="getTeamSummary" result="getTeamSummaryResult(event)" />
	<s:CallResponder id="getGameSummary" result="getGameSummaryResult(event)" />
 
	<football:TeamService id="teamService" />
	<football:TeamSummaryService id="teamSummaryService" />
	<football:GameSummaryService id="gameSummaryService" />
</fx:Declarations>

The application is very simple. When a user clicks on a team, the teamChangeHandler() is called. The handler queries the LCDS backend and sets the CallResponder‘s token property. When the asynchronous backend eventually returns some data, the data is forwarded to the appropriate result handler. In the result handler, the incoming PASO has it’s properties are formatted and then assigned to the matching form element for display.

Files

 7.15

In Part 1, I covered the basic setup of LiveCycle Data Services 3 Beta sitting on a MySQL database. Now, I’ll get into the Flash Builder side of things, and talk about the Modeler plugin and model driven development.

Setup Modeler Plugin
  1. Get Flash Builder 4 Beta (download)
  2. Get the LCDS Modeler plugin (download)
  3. Install the Modeler plugin:
    • Unzip to a temp folder, which will create a plugins folder
    • Copy the plugins folder’s contents directly into Flash Builder’s plugins folder (typically located in /Applications/Adobe Flash Builder Beta/plugins if you are on a Mac)
    • Restart Flash Builder
Model Driven Development
  1. Create a new Flex project
    • In Flash Builder, right-click and say New > Flex Project
      new flex project
      enlarge
    • Choose J2EE for Application Server Type, and select LCDS
    • Click Next to configure your server
      j2ee server config
      enlarge
    • Uncheck Use Default Location, and fill in your root folder, url, and context (see screenshot)
    • Click Validate Configuration (this will fail if LCDS is not running), and then Finish
  2. Create a new data model
    • Select the Data/Services tab in the bottom window
    • Click the Edit Active Data Model icon in the tab’s menubar (see screenshot)
      new model
      enlarge
    • This will create a new data model for your project, and bring up MyApp.fml in the Modeler’s design view (see screenshot)
    • To see the file in the Package Explorer, click the Filters icon (see screenshot), then uncheck .* and .model
  3. Connect to the server
    • Switch to the Adobe Data Model perspective
    • In the RDS Dataview window, click the RDS Configuration icon
      rds config
      enlarge
    • Set the Context Root to myapp (because our server is running at http://localhost:8080/myapp/)
    • Click Test Connection, and then OK
  4. Verify the server’s connection to MySQL
    • In the RDS Dataview window, expand until we can see our tables
      rds dataview
      enlarge
    • Right-click on a table, and select Show Table Contents
      rds show table
      enlarge
  5. Edit the model
    • Just drag tables from the RDS Dataview to add them to the model
      edit model
      enlarge
  6. Browse the generated services and code
    • Once the model is updated, the builder automatically generates standard CRUD services. Switch back to the Flash Builder perspective, and you can view them in the Data/Services tab
      services browser
      enlarge
    • The generated code is available in the Package Explorer. Files you don’t want to touch are prefixed with an underscore. The other files, like Player.as and PlayerService.as are available for you to customize.
      generated code
      enlarge
More Docs
  1. LCDS Modeler Guide (zip)
Conclusion

Once again, that’s it. I’ll have to learn something new about LCDS before I write more.


 7.1

With the beta release of LiveCycle Data Services 3, Adobe has changed the game by bringing model driven development to the forefront. The geniuses from the entity formerly known as Macromedia have put together a compelling product if you are in the business of enterprise RIAs like us. Here are a few choice words from Adobe about the beta release.

Now on to the fun part: playing with our new toy. Vroom, vroom! In Part 1, I’ll walk through getting started with LCDS sitting on top of MySQL. Part 2 covers using the Modeler plugin in Flash Builder 4 to bring the dream of model driven development to reality.

NOTE: This article was written for LCDS 3 Beta 1, but I assume it’s mostly relevant for Beta 3 (released at AdobeMAX) and all future versions of LCDS 3.

NOTE 2: The Mac installer for Beta 3 (released at AdobeMAX) does not included the integrated Tomcat which is a huge pain in the ass for all Mac developers. I recommend you grab the integrated Tomcat out of the Windows installer.

Setup MySQL
  1. Install & start MySQL (this is an exercise for the reader, I remember it being a little painful on my Mac)
  2. Create a new db & user:
    • mysql -uroot -p
      CREATE DATABASE mydb;
      CREATE USER 'myusr'@'localhost' IDENTIFIED BY 'mypassword';
      GRANT ALL PRIVILEGES ON mydb.* TO myusr@localhost;

      NOTE: Don’t use user in any part of a username (ex: myuser doesn’t work) because it is a reserved word in MySQL.

  3. Create some sample tables:
    • mysql -umyusr -pmypassword mydb
      DROP TABLE IF EXISTS team;
      CREATE TABLE team (
        id INT NOT NULL AUTO_INCREMENT,
        name VARCHAR(150),
        PRIMARY KEY (id)
      );
       
      DROP TABLE IF EXISTS player;
      CREATE TABLE player (
        id INT NOT NULL AUTO_INCREMENT,
        name VARCHAR(150),
        NUMBER INT NOT NULL,
        salary INT NOT NULL,
        team_id INT NOT NULL,
        PRIMARY KEY (id)
      );
  4. Insert data:
    • INSERT INTO team (name) VALUES ("Denver Broncos");
      INSERT INTO team (name) VALUES ("Oakland Raiders");
       
      INSERT INTO player (name,NUMBER,salary,team_id) VALUES ("Jay Cutler", 6, 6497500, 1);
      INSERT INTO player (name,NUMBER,salary,team_id) VALUES ("Champ Bailey", 24, 8003050, 1);
      INSERT INTO player (name,NUMBER,salary,team_id) VALUES ("Eddie Royal", 19, 2539830, 1);
      INSERT INTO player (name,NUMBER,salary,team_id) VALUES ("Tony Scheffler", 88, 612480, 1);
      INSERT INTO player (name,NUMBER,salary,team_id) VALUES ("JaMarcus Russell", 2, 16872400, 2);
      INSERT INTO player (name,NUMBER,salary,team_id) VALUES ("Darren McFadden", 20, 4375000, 2);
      INSERT INTO player (name,NUMBER,salary,team_id) VALUES ("Sebastian Janikowski", 11, 2625000, 2);

      NOTE: Ignore the fact that Jay Cutler now plays for Da Bears.

Digging Deeper: Setting up a database is required, but setting up tables or inserting data is not. You can use the model driven development features of LCDS (and the Modeler plugin) to create all of your tables and data.

Setup LCDS
  1. Grab LCDS 3 Beta from Adobe Labs (download)
  2. Run installer & choose to install with bundled Tomcat (on Mac this installs to /Applications/lcds and the bundled Tomcat to /Applications/lcds/tomcat)
  3. Create a new LCDS app, by copying the template app (in lcds/tomcat/webapps/lcds) to a new folder:
    • cd /Applications/lcds/tomcat/webapps
    • cp -R lcds myapp
  4. Enable RDS (Remove Dev Services) – This enables some dev only stuff like updating the database tables on the server directly from Flash Builder. For obvious security reasons, RDS would never be running in a production environment.
    • Edit /Applications/lcds/tomcat/webapps/myapp/WEB-INF/web.xml
    • Uncomment the entire RDS section
    • Set userAppserverSecurity = false (in the newly uncommented RDS section)
  5. Update services-config.xml to avoid collisions with template lcds app:
    • cd /Applications/lcds/tomcat/webapps/myapp/WEB-INF/flex
    • Edit services-config.xml:
      • In the <channel-definition id="my-rtmp"> section, change port 2038 to port 2039
      • In the <channel-definition id="my-nio-amf"> section, change port 2880 to port 2881
      • In the <channel-definition id="my-nio-amf-poll"> section, change port 2880 to port 2881
      • In the <channel-definition id="my-nio-http"> section, change port 2880 to port 2881

    NOTE: As an alternative, you can just remove the template lcds app and skip the collision avoidance stuff above.

Setup LCDS to talk to MySQL
  1. Get MySQL Connector/J, and be sure to match the version to your MySQL version (download)
  2. Put mysql-connector-java-5.1.7-bin.jar into Tomcat’s lib folder:
    • cp mysql-connector-java-5.1.7-bin.jar /Applications/lcds/tomcat/lib/
  3. Config Tomcat to recognize your MySQL db by creating a new Context for your app:
    • cd /Applications/lcds/tomcat/conf/Catalina/localhost
    • cp lcds.xml myapp.xml
    • Add a JDBC Resource block to myapp.xml, so it looks like this:
      <Context privileged="true" antiResourceLocking="false" antiJARLocking="false" reloadable="true">
          <!-- JOTM -->
          <Transaction factory="org.objectweb.jotm.UserTransactionFactory" jotm.timeout="60"/>
       
          <!-- MySQL -->
          <Resource name="jdbc/MyDB" auth="Container" type="javax.sql.DataSource"
              maxActive="100" maxIdle="30" maxWait="10000"
              username="myusr" password="mypassword"
              driverClassName="com.mysql.jdbc.Driver"
              url="jdbc:mysql://localhost:3306/mydb?autoReconnect=true"/>
       
      </Context>
Start LCDS
  1. Point Tomcat to the bundled Tomcat installed with LCDS:
    • export CATALINA_HOME=/Applications/lcds/tomcat
    • Windows: set CATALINA_HOME=C:\lcds\tomcat
  2. Set Java to Java 6:
    • export JRE_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home
    • Windows: set JRE_HOME=C:\Program Files\Java\jdk1.6.0_14\jre
  3. Run it:
    • /Applications/lcds/tomcat/bin/catalina.sh run
    • Windows: C:\lcds\tomcat\bin\catalina.bat run
  4. Sometimes Tomcat does not get the value of JRE_HOME (usually on Windows). The caused by a hard-coded value inside catalina.sh, you’ll need to edit this file and comment out that line.
  5. Verify it all worked by browsing to:
    • http://localhost:8400/myapp/
  6. A helpful bash script that does #1 – #3 all in one shot:
    • #!/bin/bash
      export CATALINA_HOME=/Applications/lcds/tomcat
      export JRE_HOME=/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home
      /Applications/lcds/tomcat/bin/catalina.sh run
    • Windows:
      set CATALINA_HOME=C:\lcds\tomcat
      set JRE_HOME=C:\Program Files\Java\jdk1.6.0_14\jre
      C:\lcds\tomcat\bin\catalina.bat run
More Docs
  1. What’s new in LCDS 3
  2. LCDS Dev Guide (zip)
  3. Tutorial Video – awesome, 20 min long, and very worthwhile
To Be Continued…

That’s it for Part 1. LCDS should be up and running on top of MySQL. Next up, Part 2 covers the Modeler plugin and model driven development.


© 2014 saturnboy.com