Partha,
    The point of the original posting is that application developers do not need to write tons of code you want to see - it is generated or written in high-level objects used by framework.
 
Here how it works:
Step 1. You write SQL and method name so it can be used by doclet engine:
package com.cti.composition;
 
import java.sql.SQLException;
 
/**
 * @xmlsp:webservice
 *   pool=dbPool
 *
 */
public interface Employee
{
 
 /**
 * @xmlsp:method
 *  scope=public
 *  sql=::  select * from EMPLOYEE
 *  ::
 *  type=bean(EmployeeVO[])
 *  updatable=true
 *
 */
 public Object getEmployees() throws SQLException;
 
}
 
Step 2. Run build or integrated doclet in Eclipse to generate the files. Usual ratio is somewhat 100 (generated statements) to 1 (lines in manually written SQL) - that accounts for 50% of the time savings for RAD. Other 50% are coming from bug-free code as oppose to manually written one. You should get those files out:
 
Grid MXML for testing/cut and paste in your application
 
<?xml version="1.0" encoding="UTF-8"?>
<mx:Application xmlns:common="common.*" xmlns:mx="
http://www.macromedia.com/2003/mxml" backgroundColor="#FFFFFF" horizontalAlign="left" styleName="plain">
<!--XDataGrid allows you to maintain state on the client (Flex 1.5/2.0) as well as talk to the server automatically -->
<common:XDataGrid id="dg" editable="true" multipleSelection="false" width="100%" height="400" retrieveMethod="getEmployees" remoteObject="com.cti.composition.EmployeeImpl" itemClass="{com.cti.composition.EmployeeVO}">
<common:columns>
<mx:Array>
<common:XDataGridColumn columnName="EMP_ID" headerText="Emp Id" editable="false"/>
<common:XDataGridColumn columnName="MANAGER_ID" headerText="Manager Id" editable="true"/>
<common:XDataGridColumn columnName="EMP_FNAME" headerText="Emp Fname" editable="true"/>
<common:XDataGridColumn columnName="EMP_LNAME" headerText="Emp Lname" editable="true"/>
<common:XDataGridColumn columnName="DEPT_ID" headerText="Dept Id" editable="true"/>
<common:XDataGridColumn columnName="STREET" headerText="Street" editable="true"/>
<common:XDataGridColumn columnName="CITY" headerText="City" editable="true"/>
<common:XDataGridColumn columnName="STATE" headerText="State" editable="true"/>
<common:XDataGridColumn columnName="ZIP_CODE" headerText="Zip Code" editable="true"/>
<common:XDataGridColumn columnName="PHONE" headerText="Phone" editable="true"/>
<common:XDataGridColumn columnName="STATUS" headerText="Status" editable="true"/>
<common:XDataGridColumn columnName="SS_NUMBER" headerText="Ss Number" editable="true"/>
<common:XDataGridColumn columnName="SALARY" headerText="Salary" editable="true"/>
<common:XDataGridColumn columnName="START_DATE" headerText="Start Date" editable="true" cellRenderer="common.RenderEditableDate" width="102" resizable="false"/>
<common:XDataGridColumn columnName="TERMINATION_DATE" headerText="Termination Date" editable="true" cellRenderer="common.RenderEditableDate" width="102" resizable="false"/>
<common:XDataGridColumn columnName="BIRTH_DATE" headerText="Birth Date" editable="true" cellRenderer="common.RenderEditableDate" width="102" resizable="false"/>
<common:XDataGridColumn columnName="BENE_HEALTH_INS" headerText="Bene Health Ins" editable="true"/>
<common:XDataGridColumn columnName="BENE_LIFE_INS" headerText="Bene Life Ins" editable="true"/>
<common:XDataGridColumn columnName="BENE_DAY_CARE" headerText="Bene Day Care" editable="true"/>
<common:XDataGridColumn columnName="SEX" headerText="Sex" editable="true"/>
</mx:Array>
</common:columns>
</common:XDataGrid>
<common:TestXDataGrid dataGrid="{dg}" itemClass="{com.cti.composition.EmployeeVO}"/>
<mx:HRule width="100%"/>
<mx:Canvas label="getEmployees()" width="280" height="44">
<mx:Button label="Retrieve" x="20" y="10" click="dg.retrieve();"/>
<mx:Button label="Update" x="140" y="10" click="dg.update();"/>
</mx:Canvas>
<mx:Script>
 var dummy_getEmployees:com.cti.composition.EmployeeVO = null;  /* init ActionScript proxies */</mx:Script>
</mx:Application>
ActionScript bean:
/* Automatically generated file. */
dynamic class com.cti.composition.EmployeeVO
{
 public var _nulls:String;  // internals
 public var EMP_ID : Number;
 public var MANAGER_ID : Number;
 public var EMP_FNAME : String;
 public var EMP_LNAME : String;
 public var DEPT_ID : Number;
 public var STREET : String;
 public var CITY : String;
 public var STATE : String;
 public var ZIP_CODE : String;
 public var PHONE : String;
 public var STATUS : String;
 public var SS_NUMBER : String;
 public var SALARY : Number;
 public var START_DATE : Date;
 public var TERMINATION_DATE : Date;
 public var BIRTH_DATE : Date;
 public var BENE_HEALTH_INS : String;
 public var BENE_LIFE_INS : String;
 public var BENE_DAY_CARE : String;
 public var SEX : String;
 
 static var registered = Object.registerClass("com.cti.composition.EmployeeVO", com.cti.composition.EmployeeVO);
 
 public function __typeName():String { return "com.cti.composition.EmployeeVO"; }
 
 public function toString():String { return "com.cti.composition.EmployeeVO { "+" EMP_ID:"+EMP_ID+" MANAGER_ID:"+MANAGER_ID+" EMP_FNAME:"+EMP_FNAME+" EMP_LNAME:"+EMP_LNAME+" DEPT_ID:"+DEPT_ID+" STREET:"+STREET+" CITY:"+CITY+" STATE:"+STATE+" ZIP_CODE:"+ZIP_CODE+" PHONE:"+PHONE+" STATUS:"+STATUS+" SS_NUMBER:"+SS_NUMBER+" SALARY:"+SALARY+" START_DATE:"+START_DATE+" TERMINATION_DATE:"+TERMINATION_DATE+" BIRTH_DATE:"+BIRTH_DATE+" BENE_HEALTH_INS:"+BENE_HEALTH_INS+" BENE_LIFE_INS:"+BENE_LIFE_INS+" BENE_DAY_CARE:"+BENE_DAY_CARE+" SEX:"+SEX+", _nulls="+_nulls+" }";}
}
Java Bean
 
 

/* Automatically generated file. */
package com.cti.composition;
import java.util.Date;
 
public class EmployeeVO
{
 public String _nulls; // internals
 public int EMP_ID;
 public int MANAGER_ID;
 public String EMP_FNAME;
 public String EMP_LNAME;
 public int DEPT_ID;
 public String STREET;
 public String CITY;
 public String STATE;
 public String ZIP_CODE;
 public String PHONE;
 public String STATUS;
 public String SS_NUMBER;
 public double SALARY;
 public java.util.Date START_DATE;
 public java.util.Date TERMINATION_DATE;
 public java.util.Date BIRTH_DATE;
 public String BENE_HEALTH_INS;
 public String BENE_LIFE_INS;
 public String BENE_DAY_CARE;
 public String SEX;
 

 public EmployeeVO()
 {
 }
 
 public String toString()
 {
  return "com.cti.composition.EmployeeVO { "+" EMP_ID:"+EMP_ID+" MANAGER_ID:"+MANAGER_ID+" EMP_FNAME:"+EMP_FNAME+" EMP_LNAME:"+EMP_LNAME+" DEPT_ID:"+DEPT_ID+" STREET:"+STREET+" CITY:"+CITY+" STATE:"+STATE+" ZIP_CODE:"+ZIP_CODE+" PHONE:"+PHONE+" STATUS:"+STATUS+" SS_NUMBER:"+SS_NUMBER+" SALARY:"+SALARY+" START_DATE:"+START_DATE+" TERMINATION_DATE:"+TERMINATION_DATE+" BIRTH_DATE:"+BIRTH_DATE+" BENE_HEALTH_INS:"+BENE_HEALTH_INS+" BENE_LIFE_INS:"+BENE_LIFE_INS+" BENE_DAY_CARE:"+BENE_DAY_CARE+" SEX:"+SEX+", nulls="+_nulls+" }";
 }
}
 
Java DAO method:
 
 
 
/* Automatically generated file. */
package com.cti.composition;
 
import java.sql.*;
import java.util.*;
//import com.cti.util.dao.*;
import com.cti.daoflex.*;
 

public final class EmployeeImpl extends DaoBase  /*implements Employee */
{
 public EmployeeImpl()
 {
  if( DEBUG ) trace("EmployeeImpl()");
 }
 

 public final EmployeeVO[] getEmployees() throws SQLException
 {
  if( DEBUG ) trace("getEmployees(...)");
  String _sql = "select * from EMPLOYEE";
  EmployeeVO[] _res = null;
  ArrayList _lst = new ArrayList();
  PreparedStatement _stmt = null;
  ResultSet _rs = null;
  Connection _conn = null;
  try
  {
   _conn = getConnection("dbPool");
   if( DEBUG ) trace(" SQL: "+_sql);
   _stmt = _conn.prepareStatement(_sql);
   _rs   = _stmt.executeQuery();
   StringBuffer _nulls = new StringBuffer(256);
   long _rowCount = 0;
   while( _rs.next() )
   {
    _rowCount++;
    EmployeeVO _item = new EmployeeVO();
    _item.EMP_ID = (_rs.getInt(1)); if( _rs.wasNull() ) { if( _nulls.length()>0 ) _nulls.append('|'); _nulls.append("EMP_ID"); }
    _item.MANAGER_ID = (_rs.getInt(2)); if( _rs.wasNull() ) { if( _nulls.length()>0 ) _nulls.append('|'); _nulls.append("MANAGER_ID"); }
    _item.EMP_FNAME = (_rs.getString(3)); if( _rs.wasNull() ) { if( _nulls.length()>0 ) _nulls.append('|'); _nulls.append("EMP_FNAME"); }
    _item.EMP_LNAME = (_rs.getString(4)); if( _rs.wasNull() ) { if( _nulls.length()>0 ) _nulls.append('|'); _nulls.append("EMP_LNAME"); }
    _item.DEPT_ID = (_rs.getInt(5)); if( _rs.wasNull() ) { if( _nulls.length()>0 ) _nulls.append('|'); _nulls.append("DEPT_ID"); }
    _item.STREET = (_rs.getString(6)); if( _rs.wasNull() ) { if( _nulls.length()>0 ) _nulls.append('|'); _nulls.append("STREET"); }
    _item.CITY = (_rs.getString(7)); if( _rs.wasNull() ) { if( _nulls.length()>0 ) _nulls.append('|'); _nulls.append("CITY"); }
    _item.STATE = (_rs.getString(8)); if( _rs.wasNull() ) { if( _nulls.length()>0 ) _nulls.append('|'); _nulls.append("STATE"); }
    _item.ZIP_CODE = (_rs.getString(9)); if( _rs.wasNull() ) { if( _nulls.length()>0 ) _nulls.append('|'); _nulls.append("ZIP_CODE"); }
    _item.PHONE = (_rs.getString(10)); if( _rs.wasNull() ) { if( _nulls.length()>0 ) _nulls.append('|'); _nulls.append("PHONE"); }
    _item.STATUS = (_rs.getString(11)); if( _rs.wasNull() ) { if( _nulls.length()>0 ) _nulls.append('|'); _nulls.append("STATUS"); }
    _item.SS_NUMBER = (_rs.getString(12)); if( _rs.wasNull() ) { if( _nulls.length()>0 ) _nulls.append('|'); _nulls.append("SS_NUMBER"); }
    _item.SALARY = (_rs.getDouble(13)); if( _rs.wasNull() ) { if( _nulls.length()>0 ) _nulls.append('|'); _nulls.append("SALARY"); }
    _item.START_DATE = toUtilDate(_rs.getDate(14)); if( _rs.wasNull() ) { if( _nulls.length()>0 ) _nulls.append('|'); _nulls.append("START_DATE"); }
    _item.TERMINATION_DATE = toUtilDate(_rs.getDate(15)); if( _rs.wasNull() ) { if( _nulls.length()>0 ) _nulls.append('|'); _nulls.append("TERMINATION_DATE"); }
    _item.BIRTH_DATE = toUtilDate(_rs.getDate(16)); if( _rs.wasNull() ) { if( _nulls.length()>0 ) _nulls.append('|'); _nulls.append("BIRTH_DATE"); }
    _item.BENE_HEALTH_INS = (_rs.getString(17)); if( _rs.wasNull() ) { if( _nulls.length()>0 ) _nulls.append('|'); _nulls.append("BENE_HEALTH_INS"); }
    _item.BENE_LIFE_INS = (_rs.getString(18)); if( _rs.wasNull() ) { if( _nulls.length()>0 ) _nulls.append('|'); _nulls.append("BENE_LIFE_INS"); }
    _item.BENE_DAY_CARE = (_rs.getString(19)); if( _rs.wasNull() ) { if( _nulls.length()>0 ) _nulls.append('|'); _nulls.append("BENE_DAY_CARE"); }
    _item.SEX = (_rs.getString(20)); if( _rs.wasNull() ) { if( _nulls.length()>0 ) _nulls.append('|'); _nulls.append("SEX"); }
    if( _nulls.length()>0 ) { _item._nulls = _nulls.toString(); _nulls.setLength(0); }
    _lst.add(_item);
   }
   if( DEBUG ) trace(" row count: "+_rowCount);
   _res = new EmployeeVO[_lst.size()];
   _res = (EmployeeVO[])_lst.toArray(_res);
   return _res;
  } catch(Throwable te) {
   if( DEBUG ) trace("Exception: "+te);
   if( DEBUG ) te.printStackTrace();
   if( te instanceof SQLException )
    throw (SQLException)te;
   else
    throw new SQLException("Internal error");
  } finally
  {
   try {_rs.close(); _rs = null;} catch (Exception e){}
   try {_stmt.close(); _stmt = null;} catch (Exception e){}
   releaseConnection(_conn);
  }
 }
 
 // update callback
 public final int getEmployees_update(EmployeeVO[] items, ItemState[] states) throws SQLException
 {
....
 
 
Form:
<?xml version="1.0" encoding="UTF-8"?>
<mx:Application xmlns:common="common.*" xmlns:mx="
http://www.macromedia.com/2003/mxml" backgroundColor="#FFFFFF" horizontalAlign="left" styleName="plain">
<common:XDataForm id="df" remoteObject="com.cti.composition.EmployeeImpl" retrieveMethod="getEmployees" itemClass="{com.cti.composition.EmployeeVO}">
<common:XDataFormItem label="Emp Id" dataPath="EMP_ID" dataType="Number">
<mx:TextInput id="input_EMP_ID" width="100"/>
</common:XDataFormItem>
<common:XDataFormItem label="Manager Id" dataPath="MANAGER_ID" dataType="Number">
<mx:TextInput id="input_MANAGER_ID" width="100"/>
</common:XDataFormItem>
<common:XDataFormItem label="Emp Fname" dataPath="EMP_FNAME" dataType="String">
<mx:TextInput id="input_EMP_FNAME" width="100"/>
</common:XDataFormItem>
<common:XDataFormItem label="Emp Lname" dataPath="EMP_LNAME" dataType="String">
<mx:TextInput id="input_EMP_LNAME" width="100"/>
</common:XDataFormItem>
<common:XDataFormItem label="Dept Id" dataPath="DEPT_ID" dataType="Number">
<mx:TextInput id="input_DEPT_ID" width="100"/>
</common:XDataFormItem>
<common:XDataFormItem label="Street" dataPath="STREET" dataType="String">
<mx:TextInput id="input_STREET" width="100"/>
</common:XDataFormItem>
<common:XDataFormItem label="City" dataPath="CITY" dataType="String">
<mx:TextInput id="input_CITY" width="100"/>
</common:XDataFormItem>
<common:XDataFormItem label="State" dataPath="STATE" dataType="String">
<mx:TextInput id="input_STATE" width="100"/>
</common:XDataFormItem>
<common:XDataFormItem label="Zip Code" dataPath="ZIP_CODE" dataType="String">
<mx:TextInput id="input_ZIP_CODE" width="100"/>
</common:XDataFormItem>
<common:XDataFormItem label="Phone" dataPath="PHONE" dataType="String">
<mx:TextInput id="input_PHONE" width="100"/>
</common:XDataFormItem>
<common:XDataFormItem label="Status" dataPath="STATUS" dataType="String">
<mx:TextInput id="input_STATUS" width="100"/>
</common:XDataFormItem>
<common:XDataFormItem label="Ss Number" dataPath="SS_NUMBER" dataType="String">
<mx:TextInput id="input_SS_NUMBER" width="100"/>
</common:XDataFormItem>
<common:XDataFormItem label="Salary" dataPath="SALARY" dataType="Number">
<mx:TextInput id="input_SALARY" width="100"/>
</common:XDataFormItem>
<common:XDataFormItem label="Start Date" dataPath="START_DATE" dataType="Date">
<common:EditableDateField id="input_START_DATE"/>
</common:XDataFormItem>
<common:XDataFormItem label="Termination Date" dataPath="TERMINATION_DATE" dataType="Date">
<common:EditableDateField id="input_TERMINATION_DATE"/>
</common:XDataFormItem>
<common:XDataFormItem label="Birth Date" dataPath="BIRTH_DATE" dataType="Date">
<common:EditableDateField id="input_BIRTH_DATE"/>
</common:XDataFormItem>
<common:XDataFormItem label="Bene Health Ins" dataPath="BENE_HEALTH_INS" dataType="String">
<mx:TextInput id="input_BENE_HEALTH_INS" width="100"/>
</common:XDataFormItem>
<common:XDataFormItem label="Bene Life Ins" dataPath="BENE_LIFE_INS" dataType="String">
<mx:TextInput id="input_BENE_LIFE_INS" width="100"/>
</common:XDataFormItem>
<common:XDataFormItem label="Bene Day Care" dataPath="BENE_DAY_CARE" dataType="String">
<mx:TextInput id="input_BENE_DAY_CARE" width="100"/>
</common:XDataFormItem>
<common:XDataFormItem label="Sex" dataPath="SEX" dataType="String">
<mx:TextInput id="input_SEX" width="100"/>
</common:XDataFormItem>
</common:XDataForm>
<mx:HRule width="100%"/>
<mx:Canvas label="getEmployees()" width="280" height="44">
<mx:Button label="Retrieve" x="20" y="10" click="df.retrieve();"/>
<mx:Button label="Update" x="140" y="10" click="df.update()"/>
</mx:Canvas>
<mx:Script>
  var dummy_getEmployees:com.cti.composition.EmployeeVO = null; /* necessary to make Flex proxy code working */
 </mx:Script>
</mx:Application>
 
I will skip files for init testing, metadata integration, etc.
 
 
Step 3. Let the end-user decide what they want to see. This might be a bit unconventional to J2EE crowd, but majority of financial clients require it. Basically, they want customizable grid views - with personalization, security, etc.. So the final page uses something called "Composition" and supports pop-up designer. The metadata received from examination of the SQL is imported/synchronised to DB, application developer selects which column end-user can choose for his "views", sets up cellrenderers, styling and computed columns. Yet higher level control is dropped on the final screen (no need for DataGridColumns - they are added dynamically from DB based on user credentials/selection) - making application coding trivial task.
 
 
However, let me reiterate - any framework requires a lot of training and learning. Typical explanation of the underlying principal has been reiterated quite a few times - you can refer to Brooks "No Silver Bullet recap" or http://www.joelonsoftware.com/articles/LeakyAbstractions.html. Posting of few hundreds lines will not do you any good - as with any productivity framework you are looking at tens of thousand range, including code generators, templates and productivity tools.
 
 
Hope this helps,
Anatole Tartakovsky
 
 
 

From: Partha Sarathi Das [mailto:[EMAIL PROTECTED]
Sent: Monday, January 23, 2006 12:21 AM
To: [EMAIL PROTECTED]
Subject: Re: [flexcoders] Re: Updating the data back to database

"Just write  SQL to select the data - and     Java/Flex UI is generated for you automatically - including Java DAO, updatable datagrids, forms and master/details."
Will you please send a sample code which will do the upper mention comments.I am new in Flex.Pls send a sample code for using RemoteObject to send Request
to the server and Plain Java object will process request and return a list of Object(For Example Customer etc.) which will show in the Datagrid(View) etc.
Thanks and regards,
Partha Sarathi Das,
Ph.(Office) : 91 20 56041700  Ext. 2812
----- Original Message -----
Sent: Friday, January 20, 2006 11:53 PM
Subject: Re: [flexcoders] Re: Updating the data back to database

If you need to do it in Flex 1.5 you relally need to put significant amount of code in your base objects. We implemented in 1.5 just what Dave is suggesting with "PowerBuilder" approach ( which was considered a standard of Enterprise RAD - Rapid Application Development)- high-level objects that keep track of the state of each database record, with an ability to send the changes to the server. Unlike Flex 2, we implemented automatic generation of "updates" based on original "selects" and minimal metadata so you do not need to write your own persistence layer. Just write  SQL to select the data - and     Java/Flex UI is generated for you automatically - including Java DAO, updatable datagrids, forms and master/details. And we also placed nice toolkit on the top of it so users can select/apply their own layouts (persisted in database) in run-time if needed. Of course, code generators can be tuned for iBatis or Hibernate or any other - as long as there is justification for it.
 
Other things that I have not seen in Flex 2 but are the must for real-life applications are "transaction" services, when you can submit changes to multiple objects at once. For that we had to write specialized gateway so we would preserve AMF/HTTP infrastructure for development (called RPC in Flex 2) while adding "transactional" methodology to the calls.
 
So, it is very possible - the only bad news is that any framework as such has learning curve, especially if the team is skilled with Web technologies, and do not have PowerBuilder one. When we bring this to our customers it takes anywhere between 2 to 4 weeks of mentoring to get the team to RAD mode. While it is definetly more economical then writing all modification code for any application that is more then just few screens, and proved to produce much fewer "errors", decision to use it has to be made very early in the development process (or pilot if possible).
Hope this helps,
Anatole Tartakovsky
 
----- Original Message -----
From: Dave Wolf
Sent: Thursday, January 19, 2006 4:47 PM
Subject: [flexcoders] Re: Updating the data back to database

In Flex 1.5 there  is not.  However Flex 2.0 will include the
"Enterprise Data Services" which include exactly this functionality.
This was demonstrated at MAX last fall and Adobe has presented several
web casts on it.  As you note (and much like other existing
client/server products like PowerBuilder) the data services will
include the ability to track "changed" or "dirty" data on the client,
marshal those changes to the server, and will provide for a pluggable
persistence layer which will handle writing the changes in an
optimized way to the underlying data store.  This will include things
like optimistic updates, etc. 

--
Dave Wolf
Cynergy Systems, Inc.
Macromedia Flex Alliance Partner
http://www.cynergysystems.com

Email: [EMAIL PROTECTED]
Office: 866-CYNERGY


--- In flexcoders@yahoogroups.com, "mydmjac" <[EMAIL PROTECTED]> wrote:
>
> Does Flex provide any ways of identifying data changes made by users?
> Obviously I am new to Flex, and I noticed that there are lots of tips, 
> information on interface, controls, also how to retrieve data from the
> server. However I haven't been able to find any reference for updating
> process, some components like XUpdateResolver in Flash make it a lot
> easier to move the changes back to the server and finally to the
> database.
>







--
Flexcoders Mailing List
FAQ: http://groups.yahoo.com/group/flexcoders/files/flexcodersFAQ.txt
Search Archives: http://www.mail-archive.com/flexcoders%40yahoogroups.com




YAHOO! GROUPS LINKS




Reply via email to