Automatically generating code for Flex 2 data access

Document Sample
Automatically generating code for Flex 2 data access Powered By Docstoc
					Flex Article
Automatically generating code for Flex 2 data access

Yakov Fain

Victor Rasputnis

Anatole Tartakovsky Send feedback Get an e-mail update of new articles Created: 24 July 2006 User Level: Intermediate This article introduces DAOFlex, an open-source tool that automates some of the routine tasks in developing Adobe Flex 2 business applications. Specifically, DAOFlex can take a SQL query and a simple Java class and automatically generate, compile, and prepare all required files for the deployment of a data-driven Flex 2 application. If you're skeptical about code generator claims, then read this article and examine the rich Internet application that we developed using DAOFlex. Hopefully, this article will ignite your interest in code generators and the DAOFlex tool.

Eclipse 3.1 IDE with the Flex Builder plug-in installed. To create the sample application (ZIP, 3.83K), you'll need to provide following programming input: An SQL statement (or a stored procedure) that generates the data for your application; for example:

select * from Employee where startDt < :someStartDate
The definition of an abstract Java class, annotated with an SQL statement plus a few metatags that specify the name of the database, update requirements, and so forth. For example:

/** * @daoflex:service pool=jdbc/theriabook */ import java.util.List; public abstract class Employee{ /* * @daoflex:sql transferType= EmployeeDTO[] * sql=:select * from Employee where startDt < :startDate :: * tableName=EMPLOYEE * * keyColumns=EMP_ID * updateWhere=key_and_modified * / public abstract List getEmployees(Date startDate); }

A .properties file that contains everything needed for DaoFlex to establish a JDBC connection to your DBMS. Running DBMS (MySQL database backup SQL for sample employee table can be found here.) A build script (supplied in the ZIP file (ZIP, 9.11 MB) that accompanies this article). DaoFlex Code Generator (JAR, 78.4K) and DaoFlex Run-time libraries (JAR, 12.9K) Prerequisite knowledge: A basic understanding of Adobe Flex 2, Java syntax, Apache Ant, and SQL.

Overview: What's the big idea?
After repeatedly performing the same routines—writing Java JDBC calls, declaring the Data Transfer Objects (DTO) in Java and ActionScript, mapping and customizing DataGrid columns and form items, defining standard event handlers—we decided to automate the process. So, we created and used special code templates that do the tedious work and generate the Flex and Java code for us. The DAOFlex tool that we created takes a Java abstract class containing doclet tags and produces an XML file. Next, it takes the XML file and puts it through XSL Transform to generate the required Java, MXML, and ActionScript code. Finally, an Ant script prepares all configuration files required for deployment on the Java EE application server. Finally, an Ant script compiles and packages Java files required for deployment on the Java EE application server and writes them into destination directories. Java abstract class, in Listing 1, provides SQL to retrieve data from the database. The tableName tag within Listing 1 specifies the table that is the target of updates, thus DAOFlex has enough information to generate the code for performing the database inserts, updates, and deletes.

/** * @daoflex:service pool=jdbc/theriabook */ import java.util.List; public abstract class Employee{ /* * @daoflex:sql transferType= EmployeeDTO[] * sql=select * from Employee where startDt < :startDate * tableName=EMPLOYEE * * keyColumns=EMP_ID * updateWhere=key_and_modified * / public abstract List getEmployees(Date startDate); }
Listing 1. The annotated java class, Employee After running the build script against the sample abstract java class code and updating services configuration on the server to include newly generated services, you'll have a fully functional Flex/Java application deployed to the Java EE application server of your choice. This application can use both Flex Data Services and Flex Remote Objects. The resulting application will look like Figure 1:

Figure 1. DAOFlex generated application Along the way, DAOFlex generates and deploys JARs with Java DTO, DAO and Assemblers, sample MXML, ActionScript classes, and XML for configuration files.

A sample application from start to finish
This section walks you through the entire process of creating an application that lets you display and modify the Employee data. See a step-by-step video of the process. This sample application uses the MySQL database and deploys the application under the JRun application server. This tutorial assumes that you have the Eclipse IDE with the Flex Builder plug-in installed. Step 1: Get the DaoFlex package The complete source for the DaoFlex package and sample application is included in (ZIP, 9.11MB). If you unzip it to the c:\TheRiaBook\tools\DaoFlex folder, you shouldn't need to modify any settings. If you unzipped the file in a different directory, modify the build script file at examples\build.xml. Step 2: Start code generation and deployment for Flex Data Services To start the code generation of a sample Employee application, open Eclipse IDE and create a new project in the Java perspective. Eclipse gives you an option to create a new project based on the preexisting Ant build script. DAOFlex includes this script in the examples subfolder of DaoFlex package. To run the build.xml file from the examples directory: 1. Right-click on the build.xml in the root of the project. 2. Select the Run As | Ant Build menu. 3. Select the Ant task build-original. The DaoFlex doclet automatically retrieves the database metadata related to the result of the query and combines it with the metadata provided by the file. By using this combined metadata and running prewritten XSLT stylesheets against it, DaoFlex will generate the following:

Java and ActionScript versions of the EmployeeDTO class Implementation of the abstract data access object (DAO) for remoting Implementation of DAO and Assembler for data services Configuration files for remoting and data services A test MXML application The entire process of generating the required files should not take more than a few seconds. The examples folder Next, let's examine the content of the examples folder, which contains the following subfolders and files: src: The directory that contains the source code for the class jdbc: The file that defines the JDBC driver and the data source. For example, the test database on localhost would have the following properties: driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/test... generated\metadata: This folder contains the XML for the metadata files generated by DaoFlex generated\java: This folder contains the Java files generated by DAOFlex: Java DTO, DAO, Assemblers generated\web: This folder contains the MXML, ActionScript and services configuration files. build.xml: The Ant script file for our sample application. This file contains the "build-original" task that we'll run later. The file The file is located in the src directory and contains the source for the class: has an abstract method, getEmployees(). Because getEmployees() is declared as an abstract method, it must be implemented in an class descendent. getEmployees() has only one parameter, startDate. Notice (in Listing 1) that this parameter maps to a binding variable with the same name in the tag @daoflex:sql. getEmployees() returns a collection of DTO objects with a specified type of transferType=EmployeeDTO[]. The definition of this DTO is generated automatically. The key columns are specified as keyColumns=EMP_ID, which performs the same role as <identity property="EMP_ID"/> in the FDS descriptor. To add update capabilities to the generated application, we used the tablName=Employee attribute. The data source that represents the database connection pool is annotated on the class level as pool=jdbc/theriabook. The name of the properties file must match the name used in the pool parameter. Individual methods can override this setting, and can use different connection pools. The build.xml script The build.xml script creates two .jar files: The first jar file includes the generated DAOs, DTOs, and Assemblers (daoflex-examples-generated.jar). The second jar file contains abstract DAO classes (daoflex-examples.jar). The following code snippet from build.xml describes the location of the deployment directory within the JRun server that came with Flex Data Services:

<property name="deployment.web.root" value="C:/fds/jrun4/servers/default/theriabook"/> <property name="original.jar.destination" value="${deployment.web.root}/WEB-INF/lib/daoflex-examples.jar"/> <property name="generated.jar.destination" value="${deployment.web.root}/WEB-INF/lib/daoflex-examplesgenerated.jar"/>

The Flex development perspective in Eclipse
Now, let's switch to the Flex development perspective in Eclipse and create a new Flex project using the Data Services compiled locally option. Step 1: Specify the location of the application server Specify the location of your application server with deployed FDS and, for JRun, the screen might look similar to Figure 2.

Figure 2. Specifying the location of the application server with FDS Notice that we set the default web context to be theriabook. Step 2: Map the location of the Project Contents On the New Flex Project screen, map the location of the Project Contents to the generated web directory as shown in Figure 3.

Figure 3. Selecting the Project Contents location Step 3: Copy and paste the auto-generated Employee destination Although DAOFlex generated all the code, you must make some manual modifications. The client application from Figure 1 will communicate with an FDS destination Employee, which can be configured in the data-management-config.xml file. Copy and paste the following auto-generated definition of the Employee destination from ...\examples\generated\web\WEB-INF\flex\flex-data-service.Employee.xml to the data-management-config.xml in the application server's directory.

<destination id="Employee"> <adapter ref="java-dao" /> <properties> <source>com.theriabook.datasource.EmployeeAssembler</source> <scope>application</scope> <metadata> <identity property="EMP_ID" /> </metadata> <network> <session-timeout>0</session-timeout> <paging enabled="false" /> <throttle-inbound policy="ERROR" max-frequency="500" /> <throttle-outbound policy="ERROR" max-frequency="500" /> </network> <server> <fill-method> <name>getEmployees</name> <params>java.util.Date</params> </fill-method> <sync-method> <name>getEmployees_sync</name> </sync-method> </server> </properties> </destination>
This destination declares the getEmployees() fill-method with one parameter of type java.util.Date, an identity property named EMP_ID, and the getEmployees_sync() method that will take care of the database updates. Step 4: Copy and paste the MXML file The daoflex\examples\generated\web\test\ds\com\theriabook\datasource directory contains the generated MXML files. Now, let's take the FDS version Employee_getEmployees_GridTest.mxml, and copy its content into the empty Main.mxml default application file in your Flex Builder project. Step 5: Run your project Start your application server and run your project in Flex Builder 2, which will open the application (Figure 4).

Figure 4. Running the Main.mxml application Step 6: Populate the data grid To populate the data grid, click the Fill button. To add an empty row at the top of the grid, click the Insert button. Since the Employee database table has multiple columns defined with the Not Null constraint, forgetting to provide the values for the columns will cause exceptions to be thrown. These exceptions will be propagated from JDBC methods to FDS and then to the onFault event handler in the MXML client. These errors will be displayed at the bottom of the window in the log data grid, as shown in Figure 5

Figure 5. Reporting errors To test updates, make some data changes in the top grid, and click the Commit button followed by the Fill button to verify that the data were actually updated in the database. Let's take a look at the fragment of the generated MXML code that you pasted into the Main.mxml:

<?xml version="1.0" encoding="UTF-8"?> <mx:Application xmlns:mx="" backgroundColor="#FFFFFF" creationComplete="onCreationComplete()"> <mx:DataService id="ds" autoCommit="false" destination="Employee" conflict="logEvent(event)" fault="logEvent(event)" /> <mx:VDividedBox width="800" height="100%"> <mx:Panel title="Employee::getEmployees()" width="800" height="70%"> <mx:DataGrid id="dg" dataProvider="{collection}" editable="true" height="100%"> <mx:columns> <mx:Array> <mx:DataGridColumn dataField="EMP_ID" headerText="Emp Id" editable="true" itemEditor="{numberEditor}" labelFunction="numberLabelFunction"/> <mx:DataGridColumn dataField="MANAGER_ID" headerText="Manager Id" editable="true" itemEditor="{numberEditor}" labelFunction="numberLabelFunction"/> <mx:DataGridColumn dataField="EMP_FNAME" headerText="Emp Fname" editable="true"/> <mx:DataGridColumn dataField="EMP_LNAME" headerText="Emp Lname" editable="true"/> ... <mx:DataGridColumn dataField="START_DATE" headerText="Start Date" editable="true" itemEditor="mx.controls.DateField" editorDataField="selectedDate"/> ...
Listing 2. Code snippets from the MXML code generated by DAOFlex The code in Listing 2 contains the <mx:DataService> tag that points at the server destination Employee, the <mx:DataGrid> control with the array of <mx:DataGridColumn> columns shows the list of employees retrieved from the database. DAOFlex recognized different data types and generated appropriate item renderers/editors and label functions.

Using the sample with the RemoteObject tag
If you're not planning to use FDS, but intend to use this sample with the RemoteObject tag, you'll have to copy the following code fragment from flex-remoting-service.Employee.xml to your remoting-config.xml file:

<destination id="com.theriabook.datasource.EmployeeRemotingDAO"> <properties> <source>com.theriabook.datasource.EmployeeRemotingDAO</source> </properties> </destination>
You will also need to use RPC version of MXML sample located in the daoflex\examples\generated\web\test\rpc\com\theriabook\datasource folder.

Peeking under the DAOFlex hood
The structure of all generated files is controlled by the stylesheets located in the daoflex\xsl folder. If you know XSL programming, the following code fragment will look familiar:

<xsl:template match="SQL | METHOD" mode="buttons"> <mx:Button click="fill_onClick()" label="Fill" /> <xsl:if test="UPDATE/@ENABLED='Y'"> <mx:Button enabled="{{(dg.selectedIndex!=-1)}}" click="delete_onClick()" label="Delete"/> <mx:Button enabled="{{(dg.selectedIndex!=-1)}}" click="insert_onClick()" label="Insert"/> <mx:Button click="append_onClick()" label="Append" /> <mx:Button enabled="{{ds.commitRequired}}" click="commit_onClick()" label="Commit"/> </xsl:if> </xsl:template>
DAOFlex does not require knowledge of XSL—all of the dirty work has already been done for you. But, if this article has inspired you to customize the existing DAOFlex templates or add your own templates, then the knowledge of XSL will come very handy. Examining the generated Java files To examine the generated Java files, create a new Eclipse project using the same build.xml file, but this time run it by selecting the build-generated target. Several seconds later you'll find the source code of the following Java classes:
EmployeeDTO EmployeeAssembler

EmployeeDataServiceDAO EmployeeRemotingDAO

The most interesting class is EmployeeDataServiceDAO, which contains methods to create, update, delete, retrieve, and sync the employees' data. Doclet code samples The following code samples will give you an idea of other parameters and tags available in DaoFlex code generator. Sample 1: Java Dao classes generated by DAOFlex will contain both the getEmployees() fill-method and the getEmployees_sync() sync-method, since the tableName parameter is set. In this sample, only two columns, phone and salary, will be updatable, since the updatableColumns parameter is applied.

/** * @daoflex:sql * sql=:: select * from employee where * start_date < :startDate or start_date=:startDate * :: * transferType=EmployeeDTO[] * keyColumns=emp_id * updateTable=employee * updatableColumns=phone,salary */ public abstract List getEmployees();
In addition to predefined tags, DAOFlex allows you to specify a list of arbitrary user-defined name/value pairs delimited by semicolon. These name/value pairs extend standard DAOFlex metadata and can be to customize the DAOFlex stylesheets Sample 2: In this sample, a user-defined tag sqlCallback contains the name of the method that will be used by the customized version of a DAOFlex XSL Stylesheet to massage the WHERE clause of the SQL SELECT statement before building the JDBC PreparedStatement:

/** * @daoflex:sql * sql=select * from employee * transferType=anypackage.EmployeeDTO[] * keyColumns=emp_id * tag=sqlCallback:modifyGetEmployeeSQL;other_custom_tag:value */ public abstract List searchEmployees(Map context); protected String modifyGetEmployeeSQL(Map context, String sql) { // Whatever you feel like doing with the SQL goes here String whereClause = (String)context.get("where"); if (whereClause != null) { return sql + " WHERE " + whereClause; } else { return sql; } }
Sample 3: This sample shows the use of the sp_get_employee stored procedure as a source of the result set. (DAOFlex 1.0 assumes that a stored can return a result set, which may not be true for each DBMS.) To figure out which of the many possible result sets is expected, the code generation phase of DAOFlex might require sample values of input parameters, presented via separate @daoflex:param tags.

//CREATE PROCEDURE sp_get_employee (IN empId INT) //BEGIN // select * from employee where emp_id=eid; //END // /** * @daoflex:sql * procedure = sp_get_employee * transferType=EmployeeDTO[] * @daoflex:param name=empId * value=101 */ public abstract List getEmployeeProc();
In addition to handling the result set, DAOFlex can take care of the INSERT/DELETE/UPDATE operations. This feature is applicable only to the Remoting flavor of DAO .

/** @daoflex:sql * sql=DELETE from employee where emp_id=:empId */ public void removeEmployee (int empId);
Individual methods can override the settings of the class-wide database connection via the pool parameter of the @daoflex:sql tag:

/** @daoflex:sql * sql=INSERT INTO employee (emp_id, emp_lname, emp_fname) VALUES (:empId, :lName, :fName) * pool=jdbc/sample/connectionPool */ public void addEmployee(int empId, String lName, String fName);
Sample 4: This sample shows how to specify an SQL Update:

/** @daoflex:sql * sql=UPDATE employee SET emp_lname=:lname, emp_fname=:fname

where emp_id=:empId */ public void updateEmployeeById(int empId, String lname, String fname);
You can also use DaoFlex to generate ActionScript counterparts to Java classes, proxies to other ERP systems, and so forth. Depending on the requirements, you can add or remove code generating templates and customize them to support any type of the framework that you need.

Downloading the DAOFlex component code
The DAOFlex component 1.0 is licensed under the GNU General Public License (see You can download, use, and distribute the code for any use; however, you must cite Farata Systems as the original author of this code. The source code of the DAOFlex component is located in the dist folder, which has two subfolders: runtime and generator, where the. doclets are defined. The Java source code of the DAOFlex component is located in the dist folder, which has two subfolders: runtime and generator. The XSL templates are located in xsl folder. For more details, you can watch the audio/video presentation that shows this application in action. See Your programming experience with Flex 2 should allow you to be creative, and it's a good idea to minimize the time spent on tedious jobs such as writing Java DAO classes, or mapping MXML tags to database table columns and keeping them in sync. The DAOFlex component will do this routine job for you by generating code for the data manipulation, which will turn Flex 2 into an accelerated application development tool. From a best practices perspective, when it comes to adding a data grid to your screen, do not program it manually. Spend a half-hour writing your SQL and creating an annotated Java class as described in this tutorial. Then, click the button and, 10 seconds later, copy and paste the generated code into your application where it belongs. Meanwhile, JARs with the corresponding DAO, DTO, and Assemblers will be already loaded into WEB-INF/lib of your application. Java developers interested in design and development of their own code generators might also consider using annotations (instead of doclets) and the APT tool introduced in Java 5.0.

About the authors
Yakov Fain is a managing principal of Farata Systems. He's responsible for the enterprise architecture and emerging technologies. Yakov authored several Java books, dozens of technical articles, and his blog is hugely popular. Sun Microsystems has nominated and awarded Yakov with the Java Champion title. He leads the Princeton Java Users Group. Yakov holds a BS and an MS in Applied Math. Victor Rasputnis is a managing principal of Farata Systems. He's responsible for providing architectural design, implementation management, and mentoring to companies migrating to XML Internet technologies. He holds a Ph.D. in computer science from the Moscow Institute of Robotics. Anatole Tartakovsky is a managing principal of Farata Systems. He's responsible for the creation of frameworks and reusable components. Anatole authored a number of books and articles on AJAX, XML, Internet, and client-server technologies. He holds an MS in mathematics.

Copyright © 2006 Adobe Systems Incorporated. All rights reserved.

Shared By: