Granite Data Service 延时加载的问题

在创建大的工程项目时,从granite builder产生很多domain的as类,如果有些类在单个XMLApplication 项目中没有明确引用,会产生如下问题

ArgumentError: Error #2173: 无法读取流中的对象。类 org.granite.messaging.persistence.ExternalizablePersistentSet 虽未实现 flash.utils.IExternalizable,但由其别名可得知它为 externalizable 类。
    at ObjectInput/readObject()
    at org.im.scm.domain::MaterialCatalogBase/readExternal()[E:\workspace\scmSystem\as3\org\im\scm\domain\MaterialCatalogBase.as:154]
    at ObjectInput/readObject()
    at mx.collections::ArrayList/readExternal()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\collections\ArrayList.as:443]
    at mx.collections::ArrayCollection/readExternal()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\collections\ArrayCollection.as:132]
 

 

[RPC Fault faultString="Didn't receive an acknowledge message" faultCode="Server.Acknowledge.Failed" faultDetail="Was expecting mx.messaging.messages.AcknowledgeMessage, but received null"]

经过测试有两种办法解决:

1、将所有的granite builder产生的as代码包含在一个SWC中,xmlApplication项目中明确包含编译产生的SWC文件的所有类,会产生编译后SWF变大

2、在编译命令中加入如下参数:

 -include-libraries  "E:/applications/flex Framworks/libs/graniteds2.0GA/granite-essentials.swc"

也可以解决如上问题。

 

同时要注意WEB-INF/web.xml的配置:

 

XML/HTML代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee   http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">  
  5.     <description>  
  6.         my first Granite Data Service and Spring framework  
  7.     </description>  
  8.     <display-name>GraniteDS Spring</display-name>  
  9.     <context-param>  
  10.         <description>Path to spring config</description>  
  11.         <param-name>contextConfigLocation</param-name>  
  12.         <param-value>  
  13.             /WEB-INF/classes/applicationContext.xml  
  14.         </param-value>  
  15.     </context-param>  
  16.     <!– uncomment this block –>  
  17.     <context-param>  
  18.         <param-name>servicesConfigPath</param-name>  
  19.         <param-value>/WEB-INF/flex/services-config.xml</param-value>  
  20.     </context-param>  
  21.     <context-param>  
  22.         <param-name>graniteConfigPath</param-name>  
  23.         <param-value>/WEB-INF/granite/granite-config.xml</param-value>  
  24.     </context-param>  
  25.   
  26.     <!– JPA hibernate session filter 这个地方是解决服务端的延时加载报错–>  
  27.     <filter>  
  28.         <filter-name>SpringOpenEntityManagerInViewFilter</filter-name>  
  29.         <filter-class>  
  30.             org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter  
  31.         </filter-class>  
  32.     </filter>  
  33.       
  34.     <filter-mapping>  
  35.         <filter-name>SpringOpenEntityManagerInViewFilter</filter-name>  
  36.         <url-pattern>/*</url-pattern>  
  37.     </filter-mapping>  
  38.   
  39.     <!– Granite Data Service AMF Message Filter –>  
  40.     <filter>  
  41.         <filter-name>AMFMessageFilter</filter-name>  
  42.         <filter-class>  
  43.             org.granite.messaging.webapp.AMFMessageFilter  
  44.         </filter-class>  
  45.     </filter>  
  46.     <filter-mapping>  
  47.         <filter-name>AMFMessageFilter</filter-name>  
  48.         <url-pattern>/graniteamf/*</url-pattern>  
  49.     </filter-mapping>  
  50.     <listener>  
  51.         <listener-class>  
  52.             org.springframework.web.context.ContextLoaderListener  
  53.         </listener-class>  
  54.     </listener>  
  55.     <listener>  
  56.         <listener-class>  
  57.             org.springframework.web.context.request.RequestContextListener  
  58.         </listener-class>  
  59.     </listener>  
  60.     <listener>  
  61.         <listener-class>  
  62.             org.granite.config.GraniteConfigListener  
  63.         </listener-class>  
  64.     </listener>  
  65.     <servlet>  
  66.         <servlet-name>AMFMessageServlet</servlet-name>  
  67.         <servlet-class>  
  68.             org.granite.messaging.webapp.AMFMessageServlet  
  69.         </servlet-class>  
  70.         <load-on-startup>1</load-on-startup>  
  71.     </servlet>  
  72.     <servlet-mapping>  
  73.         <servlet-name>AMFMessageServlet</servlet-name>  
  74.         <url-pattern>/graniteamf/*</url-pattern>  
  75.     </servlet-mapping>  
  76.     <welcome-file-list>  
  77.         <welcome-file>index.jsp</welcome-file>  
  78.     </welcome-file-list>  
  79.     <login-config>  
  80.         <auth-method>BASIC</auth-method>  
  81.     </login-config>  
  82. </web-app>  

 特别要注意这一段代码:

 

web.xml配置片段
  1. <!– JPA hibernate session filter –>  
  2. <filter>  
  3.     <filter-name>SpringOpenEntityManagerInViewFilter</filter-name>  
  4.     <filter-class>  
  5.         org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter  
  6.     </filter-class>  
  7. </filter>  
  8.   
  9. <filter-mapping>  
  10.     <filter-name>SpringOpenEntityManagerInViewFilter</filter-name>  
  11.     <url-pattern>/*</url-pattern>  
  12. </filter-mapping>  

 

GraniteDS、Spring、Toplink集成的配置

配置的目的是集成granite data service ,Spring,Toplink,JPA,flex,依托adobe AMF协议进行RIA开发,测试集成的难度与开发的速度。

先贴上granite data service配置文件,关于spring的配置请参考

springtoplink集成显式事务配置

/WEB-INF/Granite/granite-config.xml

 

XML/HTML代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <!DOCTYPE granite-config PUBLIC "-//Granite Data Services//DTD granite-config internal//EN"  
  3.     "http://www.graniteds.org/public/dtd/1.2.0/granite-config.dtd">  
  4. <granite-config>  
  5.     <classgetter type="org.granite.toplink.TopLinkClassGetter"/>  
  6.     <externalizers>  
  7.         <externalizer type="org.granite.toplink.TopLinkExternalizer">  
  8.                
  9.             <include annotatedwith="javax.persistence.Entity" />  
  10.             <include annotatedwith="javax.persistence.MappedSuperclass" />  
  11.             <include annotatedwith="javax.persistence.Embeddable" />  
  12.             <!– 
  13.             <include type="org.test.model.Post"/> 
  14.             –>  
  15.         </externalizer>  
  16.     </externalizers>  
  17. </granite-config>  

/WEB-INF/flex/services-config.xml

 

XML/HTML代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2.   
  3. <services-config>  
  4.   
  5.     <services>  
  6.         <service  
  7.             id="granite-service"  
  8.             class="flex.messaging.services.RemotingService"  
  9.             messageTypes="flex.messaging.messages.RemotingMessage">  
  10.             <destination id="postService">  
  11.                 <channels>  
  12.                     <channel ref="my-graniteamf"/>  
  13.                 </channels>  
  14.                 <properties>  
  15.                     <factory>springFactory</factory>  
  16.                     <source>postService</source>  
  17.                 </properties>  
  18.             </destination>  
  19.         </service>  
  20.     </services>  
  21.     <factories>  
  22.         <factory id="springFactory" class="org.granite.messaging.service.SpringServiceFactory"/>  
  23.     </factories>  
  24.     <channels>  
  25.         <channel-definition id="my-graniteamf" class="mx.messaging.channels.AMFChannel">  
  26.             <endpoint  
  27.                 uri="http://{server.name}:{server.port}/{context.root}/graniteamf/amf"  
  28.                 class="flex.messaging.endpoints.AMFEndpoint"/>  
  29.         </channel-definition>  
  30.     </channels>  
  31.   
  32. </services-config>  

/META-INF/granite-config.properties

#for toplink

classGetter=org.granite.toplink.TopLinkClassGetter

/WEB-INF/web.xml

 

XML/HTML代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee   http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">  
  5.     <description>  
  6.         my first Granite Data Service and Spring framework  
  7.     </description>  
  8.     <display-name>GraniteDS Spring</display-name>  
  9.     <context-param>  
  10.         <description>Path to spring config</description>  
  11.         <param-name>contextConfigLocation</param-name>  
  12.         <param-value>  
  13.             /WEB-INF/classes/applicationContext.xml  
  14.         </param-value>  
  15.     </context-param>  
  16.     <context-param>  
  17.         <param-name>graniteConfigPath</param-name>  
  18.         <param-value>/WEB-INF/granite/granite-config.xml</param-value>  
  19.     </context-param>  
  20.     <context-param>  
  21.         <param-name>servicesConfigPath</param-name>  
  22.         <param-value>/WEB-INF/flex/services-config.xml</param-value>  
  23.     </context-param>  
  24.     <filter>  
  25.         <filter-name>AMFMessageFilter</filter-name>  
  26.         <filter-class>  
  27.             org.granite.messaging.webapp.AMFMessageFilter  
  28.         </filter-class>  
  29.     </filter>  
  30.     <filter-mapping>  
  31.         <filter-name>AMFMessageFilter</filter-name>  
  32.         <url-pattern>/graniteamf/*</url-pattern>  
  33.     </filter-mapping>  
  34.     <listener>  
  35.         <listener-class>  
  36.             org.springframework.web.context.ContextLoaderListener  
  37.         </listener-class>  
  38.     </listener>  
  39.     <listener>  
  40.         <listener-class>  
  41.             org.springframework.web.context.request.RequestContextListener  
  42.         </listener-class>  
  43.     </listener>  
  44.     <listener>  
  45.         <listener-class>  
  46.             org.granite.config.GraniteConfigListener  
  47.         </listener-class>  
  48.     </listener>  
  49.     <servlet>  
  50.         <servlet-name>AMFMessageServlet</servlet-name>  
  51.         <servlet-class>  
  52.             org.granite.messaging.webapp.AMFMessageServlet  
  53.         </servlet-class>  
  54.         <load-on-startup>1</load-on-startup>  
  55.     </servlet>  
  56.     <servlet-mapping>  
  57.         <servlet-name>AMFMessageServlet</servlet-name>  
  58.         <url-pattern>/graniteamf/*</url-pattern>  
  59.     </servlet-mapping>  
  60.     <welcome-file-list>  
  61.         <welcome-file>index.jsp</welcome-file>  
  62.     </welcome-file-list>  
  63.     <login-config>  
  64.         <auth-method>BASIC</auth-method>  
  65.     </login-config>  
  66. </web-app>  

 案例代码下载:点击下载此文件

GDS POJO Helloworld例子(2)

续上章

1、 增加flex 项目

a. 增加flex框架到项目中,右击项目名称,找到Flex Project Nature,选中 Add Flex Project Nature.

clip_image002

不要选中任何服务,一路回车结束后,调整Flex Complier的选项,将输入目录清空、将自动产生调试框架禁用、将src改为flex后将src目录中的文件剪切到flex目录中,删除src。

clip_image004

b. 配置Flex Complier

在命令行加入如下参数:

clip_image006

-services 的参数指向上面创建的services-config.xml文件。

c. 编辑Flex Client代码

代码如下:

 

helloworldApp.mxml
  1. <?xml version="1.0" encoding="utf-8"?>  
  2.   
  3. <mx:Application  
  4.   
  5. xmlns:mx="http://www.adobe.com/2006/mxml"  
  6.   
  7. backgroundGradientColors="[#0e2e7d, #6479ab]"  
  8.   
  9. layout="vertical"  
  10.   
  11. verticalAlign="middle">  
  12.   
  13. <mx:Style>  
  14.   
  15. .Panel {  
  16.   
  17. padding-left: 8px; padding-top: 8px;  
  18.   
  19. padding-right: 8px; padding-bottom: 8px;  
  20.   
  21. }  
  22.   
  23. .Result { font-size: 26px; color: white; }  
  24.   
  25. </mx:Style>  
  26.   
  27. <mx:RemoteObject id="srv" destination="helloWorldService" />  
  28.   
  29. <mx:Panel styleName="Panel" title="Hello World Sample">  
  30.   
  31. <mx:Label text="Enter your name:"/>  
  32.   
  33. <mx:TextInput id="nameInput" />  
  34.   
  35. <mx:Button label="Say Hello" click="srv.sayHello(nameInput.text)"/>  
  36.   
  37. </mx:Panel>  
  38.   
  39. <mx:Label styleName="Result" text="{srv.sayHello.lastResult}"/>  
  40.   
  41. </mx:Application>  

2、 发布

将项目发布到Tomcat6.0服务中就可以通过URL:http://localhost:8080/helloworldApp进行访问。

3、 小结

通过GDS可以进行简单的POJO构建应用,不过这种方法还不适用大型企业应用,下一章将熟悉GDS与Hibernate的结合应用,GDS可以将Hibernate的Bean通过GAS3功能转换为AS3的数据模型。

GDS POJO Helloworld例子(1)

环境:myeclipse 6.6,flex builder plugin 3.0,GDS 1.2spa,tomcat 6.0

1、 安装

从略。。。

2、 创建JAVA项目

a. 首先安装后启动Myeclipse环境,创建JAVA项目

clip_image002

b. 重名Src为java以区分flex的src。

clip_image004

c. 创建新HelloworldService POJO,并实现sayHello方法。

clip_image006

代码视图:

clip_image008

a. 增加WEB项目兼容包

clip_image002[3]

d. 拷贝GDS包到lib中

clip_image004[3]

e. 配置WEB.xml

代码:

 

web.xml
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2.   
  3. <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"  
  4.   
  5. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">  
  6.   
  7. <!– general information about this web application –>  
  8.   
  9. <description>Hello World Sample Application</description>  
  10.   
  11. <display-name>Hello World App</display-name>  
  12.   
  13. <!– handle AMF requests ([de]serialization) –>  
  14.   
  15. <filter>  
  16.   
  17. <filter-name>AMFMessageFilter</filter-name>  
  18.   
  19. <filter-class>org.granite.messaging.webapp.AMFMessageFilter</filter-class>  
  20.   
  21. </filter>  
  22.   
  23. <filter-mapping>  
  24.   
  25. <filter-name>AMFMessageFilter</filter-name>  
  26.   
  27. <url-pattern>/graniteamf/*</url-pattern>  
  28.   
  29. </filter-mapping>  
  30.   
  31. <!– read services-config.xml file at web application startup –>  
  32.   
  33. <listener>  
  34.   
  35. <listener-class>org.granite.config.GraniteConfigListener</listener-class>  
  36.   
  37. </listener>  
  38.   
  39. <!– handle AMF requests (execution) –>  
  40.   
  41. <servlet>  
  42.   
  43. <servlet-name>AMFMessageServlet</servlet-name>  
  44.   
  45. <servlet-class>org.granite.messaging.webapp.AMFMessageServlet</servlet-class>  
  46.   
  47. <load-on-startup>1</load-on-startup>  
  48.   
  49. </servlet>  
  50.   
  51. <servlet-mapping>  
  52.   
  53. <servlet-name>AMFMessageServlet</servlet-name>  
  54.   
  55. <url-pattern>/graniteamf/*</url-pattern>  
  56.   
  57. </servlet-mapping>  
  58.   
  59. <!– default content for helloworld application –>  
  60.   
  61. <welcome-file-list>  
  62.   
  63. <welcome-file>helloworldApp.swf</welcome-file>  
  64.   
  65. </welcome-file-list>  
  66.   
  67. <login-config>  
  68.   
  69. <auth-method>BASIC</auth-method>  
  70.   
  71. </login-config>  
  72.   
  73. </web-app>  

f. 配置services-config.xml

在WEB-INF创建Flex目录,在新建的Flex目录中创建services-config.xml文件。

clip_image006[3]

Services-config.xml代码:

 

services-config.xml
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2.   
  3. <services-config>  
  4.   
  5. <services>  
  6.   
  7. <service  
  8.   
  9. id="granite-service"  
  10.   
  11. class="flex.messaging.services.RemotingService"  
  12.   
  13. messageTypes="flex.messaging.messages.RemotingMessage">  
  14.   
  15. <destination id="helloWorldService">  
  16.   
  17. <channels>  
  18.   
  19. <channel ref="my-graniteamf"/>  
  20.   
  21. </channels>  
  22.   
  23. <properties>  
  24.   
  25. <scope>application</scope>  
  26.   
  27. <source>org.test.HelloworldService</source>  
  28.   
  29. </properties>  
  30.   
  31. </destination>  
  32.   
  33. </service>  
  34.   
  35. </services>  
  36.   
  37. <channels>  
  38.   
  39. <channel-definition id="my-graniteamf" class="mx.messaging.channels.AMFChannel">  
  40.   
  41. <endpoint  
  42.   
  43. uri="http://{server.name}:{server.port}/{context.root}/graniteamf/amf"  
  44.   
  45. class="flex.messaging.endpoints.AMFEndpoint"/>  
  46.   
  47. </channel-definition>  
  48.   
  49. </channels>  
  50.   
  51. </services-config>  

这个文件在GDS服务启动时会读取分析他,而在Flex编译时也要通过命令行编译他。

到此GDS Pojo HelloworldService的配置已经结束。

Granite数据服务:Flex DS的开源替代品

Granite数据服务(granite data services,GDS)是adobe生命周期数据服务(LiveCycle Data Services)和最近开源的BlazeDS(Blaze Data Services)的一个开源替代品。上周,GDS产品发布了1.0版本,它采用LGPL许可方式。InfoQ.com与GDS项目的创建者Franck Wolff进行了沟通,以了解更多关于该开源项目的信息。

Wolff为InfoQ.com的读者提供了GDS的概述:

GDS是adobe生命周期数据服务(LiveCycle Data Services)的一个替代品,特别强调与JEE技术的整合,包括众所周知的Java EE持久化系统(比如Ejb3/Hibernate,完全支持懒加载[lazy-loading])。GDS可以让你使用标准的flex 2及其以上版本的RemoteObjects,它们提供了来自AMF3序列化的全部优点。此外,GDS也为许多技术提供支持:

  • 与流行Web框架服务的互操作性
  • 调用服务器端的Ejb3会话Bean(无论是否使用JBoss Seam扩展)
  • 带有Acegi安全的Spring Beans
  • google Guice服务(加上Warp持久化)
  • 支持POJP服务

支持数据推(Data Push)是GDS 1.0的一个新功能。此外,GDS还提供了一个ActionScript3代码生成器(Gas3),它大大加速了flex应用的开发。GDS和Flex Builder IDE、或者免费的Flex SDK一起,可以为开发人员提供一个完整而强大的Flex应用开发、部署框架。

关于项目现状:

GDS过去比较重要的部分(Ejb3、Spring、Pojo和Gas3)已经被广泛采用,而且生产就绪,这就是我们为什么能直 接从0.4跳到1.0版本。目前引进到GDS 1.0中的新功能(Seam、Guice服务、数据推(Data Push))应该会在beta版软件中考虑到。

GDS正由Adequate Systems的两个开发人员(William Draï和我自己)积极开发。此外,由于GDS一年前就公开推出(见GDS文档),所以还有许多来自开源社区的其他人也在为GDS的开发做出贡献。GDS 确定会成为将来基于Flex的解决方案架构的服务器端核心。

关于GDS线路图和RIA架构,Wolff表示:

目前,我们正努力开发一个确保唯一性(每个实体在Flash VM中只存在一个实例)的客户端实体仓库。这个仓库的一个重要功能是当懒关联在Flex端被请求的时候,它们要透明地初始化。某种程度而言,这个功能受到了Cairngorm的启示。

线 路图中另一个重要的发展是改进GDS和JBoss Seam的集成。我认为随着RIA新的发展,从架构的角度来看,我们所面临的风险是又回到了15年前客户端/服务器模式(client/server paradigm)占主导地位的状态。这一趋势能带来与无状态服务器相互作用的有状态客户端(例如简单的数据库前端程序)。尽管这个架构对小型Flex应 用可能是可行的,但我觉得对大型应用来说,这并不是最好的选择。我想在GDS中继续致力于有状态服务器组件的设想,比如说,就像由Seam对话和任务的设 想所定义的一样。

最终的目标是在Flex端建立一个完整的数据管理系统,带有自动表单创建(实体编辑面板)和验证(它在客户端复制Hibernate验证注释)。

Wolff与读者继续分享了GDS中数据推(Data Push)的更多细节:

GDS中的数据推(命名为Gravity)被实现为一种带有通过HTTP发送的AMF3消息、类Comet技术的服务(没有 RTMP、没有特定的因特网 端口),并免费基于Bayeux协议。这种实现对Tomcat 6.0.14及其以上版本、JBoss 4.2.2及其以上版本、Jetty Continuations 6.1.15及其以上版本是可用的。就像Flex文档中描述的一样,Gravity还提供了对JMS适配器的支持。

在客户端代码中,我们 不能使用标准的mx.messaging.Consumer和mx.messaging.Producer,因为Consumer类已经从Flex 3 SDK中移除了。所以,我们要实现我们自己的、带有相同属性和方法的ActionScript类Consumer/Producer,不过有一个区别:属 性“subtopic”已改名为“topic”(是为了确保Flex 2和Flex 3之间的兼容性)。我们还创建了一个特殊的信道(org.granite.gravity.channels.GravityChannel),必须为了 数据推目的地(data push destinations)而在services-config.xml文件中使用它。简而言之,这个信道封装了两个 flash.net.URLStream实例(指令和通道),并支持长轮询(long-polling)传输。

如果你目前正在使用mx.messaging包中的类,你只需要做几个修改即可:

  1. 将所有的“mx.messaging.Consumer”imports重命名为“org.granite.gravity.Consumer”(Producer类也一样)。
  2. 将所有的“subtopic”重命名为“topic”。
  3. 修改services-config.xml中的信道定义。

Wolff还解释说明了一下Gas3的特点:

Gas3的构思是:

  1. 通过写Ejb3实体Bean设计数据库模型。
  2. 让Gas3生成复制了实体Bean属性的ActionsScript3 Beans(即Flex客户端模型Beans),而且有Hibernate工具生成数据库模式(表和索引的创建)。
  3. 用会话Bean、Spring、Guice或Pojo服务写业务逻辑。
  4. 写Flex应用(mxml)。

另外,你可以写自己的Gas3代码生成模板,还能完全自定义生成的ActionScript3类。

InfoQ让Wolff比较一下GDS和BlazeDS:

BlazeDS主要是LCDS的一个子集,它不直接提供任何数据管理功能(参见这张图片)。GDS的设计是为了提供与EJB3持 久化层的完全整合,并带来一个非常重要而独特的特征(LCDS似乎并不提供):当使用像Hibernate一样的对象/关系持久化工具时,如果你不使用任 何懒抓取策略,你可能会面临加载整个数据库的风险。GDS既支持代理(单值关联关系),也为集合支持懒抓取。

此功能基于另一种独特的序列 化特点:外部化(Externalizers)。使用标准的Flex AMF3序列化(BlazeDS或LCDS),只有非临时、非静态的公有属性才能被序列化。你不能序列化和持有ActionScript3 Bean中的私有属性,它们应该保留为私有(例如版本号等)。使用BlazeDS或LCDS实现这个目标的唯一方法是把你的实体Bean写成外部化 (Externalizable)(但是你必须同时在Java端和AS3端实现稳定的readExternal/writeExternal方法,参见这 里)。这是非常繁琐的工作,而且许多源码有潜在的、难以发现的错误(如果你没有实体Bean的源码,它甚至是不可能实现的)。使用GDS外部化,你不用把 你的Java Bean写成外部化,你还能让Gas3来生成你的AS3 Bean(强类型的,带有保持私有的私有属性和懒加载支持)。

BlazeDS 文档说BlazeDS有一个“开放适配器架构”,能让你“轻松地集成JMS、EJBs、ColdFusion组件,以及其它数据源”。从这个角度来看,由 于GDS也基于一个“开放适配器架构”,所以GraniteDS和BlazeDS并没有很大的不同。开发人员已经编写了Spring、Seam、 Guice服务适配器等。GDS还允许你自定义很多其它的东西,包括控制序列化过程的每个部分、支持特殊类型。

令人惊讶的是, BlazeDS和GDS的数据推实现都基于相同的类Comet架构类型。2007年夏季,GDS在其网站上宣布了这一实现选择,比任何BlazeDS的宣 布都要早很多。因此,除了GDS对Jetty有特别的支持(据我所知,BlazeDS只支持Tomcat)外,数据推的实现可能是非常相似的 (BlazeDS的源码还不可获得)。

Wolff提供了一个例子,说明在何处使用GDS会比使用BlazeDS有意义:

如果你是一个使用像Hibernate一样的Java EE持久化技术的软件供应商,你一定会感到支持懒抓取策略的框架的重要性。GDS最重要的特点之一(也是GDS被创建的主要原因之一)就是可能会在客户端 使用与Hibernate脫管对象(detached object)一模一样的ActionScript3拷贝,就如同你在一个规范的Java EE应用的Web层一样。使用BlazeDS的话,这似乎是根本不可能的,这意味着你不能用BlazeDS替代GDS。此外,你还可以使用Gas3的代码 生成功能,它们能实时保存。

InfoQ向Wolff询问了GDS与BlazeDS项目合并的可能性:

我还没有和Adobe讨论过这个问题。我猜测Adobe还是想保持BlazeDS和LCDS之间清晰的功能分离(在 BlazeDS中没有数据管理)。另一方面,GDS试图给出一个提供缺少功能的替代实现,它基于众所周知的、广泛采用的Java EE技术。目前我唯一可以说的就是,如果Adobe想在BlazeDS中添加GDS的一些或全部特定功能,我一定认为合并是一个合适的选择。但是在这种情 况下,对我们来说(我猜还有很多GDS用户),问题是要得到一些保证,保证未来的BlazeDS开发能满足我们的需求。

采访结束时,Wolff对开源社区表示了感谢:

我想再次感谢那些来自开源社区的人们对GDS做出的伟大贡献。

(责任编辑:A6)