欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

用GraniteDS整合Flex和Seam

程序员文章站 2022-07-16 20:40:38
...
正在学习GraniteDS,但发现资料很少,官方文档讲的比较发散,也没个简单完全的整合示例。
经过N次尝试,总算是测试调通了,其实很简单,也不知道之前为啥费了这么大劲才搞定,这就是传说中的“难了不会,会了不难”吧。

当前常用的整合框架主要有三种:
BlazeDS
官方的免费版整合框架(收费版的是LCDS),简单易用。也很稳定,稳定到2010年3月份之后就再也没更新过,其实这也是官方框架的一贯风格,稳定压倒一切。再就是API太底层,对JAVA各个框架集成程度低,不符合俺的胃口。

Flamingo
Exadel的下属项目,由于与JBoss的特殊关系所以对Seam框架的集成比较深入,支持很多独有特性。也好久没更新了,一年前就说准备支持CDI,然后就没了下文,对这个项目很不放心。

GraniteDS
这个是俺最终的选择。对Seam Spring EJB3 POJO CDI Hibernate都有很深入的集成支持,更新的也很快。
内置了一个Tide框架用来对各个框架进行深入集成,语法与Seam极其相似[In] [Out] [Observer]借鉴的很彻底,Seam开发人员一定很亲切。

版本
1. Seam 2.2.2.Final
2. Flex 4.5
3. GraniteDS 2.2.1.GA
4. JBoss 5.1.0.GA

环境准备
1. 一个可用的Seam环境,此处使用的是EAR包(自行解决^_^)
2. 安装Flash Builder 4.5并创建一个可用的Flex项目(自行解决^_^)
3. 下载GraniteDS项目包
   地址:http://www.graniteds.org/confluence/display/DOWNLOAD/Download+Links
   下载GraniteDS Core Bundle (mandatory)

配置Java端
1. 将granite.jar、granite-seam21.jar、granite-hibernate.jar三个JAR包拷贝至/archive/xxx-ear.ear/lib/下
   这些JAR包可在刚刚下载的GraniteDS项目包的build目录下找到
   build目录下还有一个granite-seam.jar包,这个是用来集成Seam 2.0的。Seam 2.1/2.2版本需要的是granite-seam21.jar包。(命名真不科学...)
   * 另外项目中不要有BlazeDS的JAR包(也就是flex-messaging-xxx.jar),否则通信时会抛错,之前被这个问题困扰很久...

2. 在src目录下创建一个空白的文件,文件名为seam.properties

3. /WEB-INF/web.xml中新增
<!-- Flex GraniteDS -->
<listener>
	<listener-class>org.granite.config.GraniteConfigListener</listener-class>
</listener>

<filter>
	<filter-name>AMFMessageFilter</filter-name> 
	<filter-class>org.granite.messaging.webapp.AMFMessageFilter</filter-class> 
</filter>
<filter-mapping>
	<filter-name>AMFMessageFilter</filter-name>
	<url-pattern>/graniteamf/*</url-pattern>
</filter-mapping>

<servlet>
	<servlet-name>AMFMessageServlet</servlet-name>
	<servlet-class>org.granite.messaging.webapp.AMFMessageServlet</servlet-class>
	<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
	<servlet-name>AMFMessageServlet</servlet-name>
	<url-pattern>/graniteamf/*</url-pattern>
</servlet-mapping>

<servlet>
	<servlet-name>GravityServlet</servlet-name>
	<servlet-class>org.granite.gravity.jbossweb.GravityJBossWebServlet</servlet-class>
	<load-on-startup>1</load-on-startup>
</servlet>    
<servlet-mapping>
	<servlet-name>GravityServlet</servlet-name>
	<url-pattern>/gravityamf/*</url-pattern>
</servlet-mapping>

GraniteConfigListener必须在SeamListener之后定义。
GravityServlet是用来支持服务器推送功能,也就是comet技术,先配置上备用。

4. /WEB-INF/components.xml中新增
<?xml version="1.0" encoding="UTF-8"?>
<components xmlns="http://jboss.com/products/seam/components"
 xmlns:async="http://jboss.com/products/seam/async"
 xmlns:core="http://jboss.com/products/seam/core"
 xmlns:international="http://jboss.com/products/seam/international"
 xmlns:persistence="http://jboss.com/products/seam/persistence"
 xmlns:security="http://jboss.com/products/seam/security"
 xmlns:transaction="http://jboss.com/products/seam/transaction"
 xmlns:web="http://jboss.com/products/seam/web"
 xmlns:graniteds="http://www.graniteds.org/config"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xsi:schemaLocation=
	"http://jboss.com/products/seam/core
		http://jboss.com/products/seam/core-2.2.xsd
 	 http://jboss.com/products/seam/transaction
		http://jboss.com/products/seam/transaction-2.2.xsd  
 	 http://jboss.com/products/seam/persistence
		http://jboss.com/products/seam/persistence-2.2.xsd  
 	 http://jboss.com/products/seam/web
		http://jboss.com/products/seam/web-2.2.xsd  
 	 http://jboss.com/products/seam/security
		http://jboss.com/products/seam/security-2.2.xsd  
 	 http://jboss.com/products/seam/async
		http://jboss.com/products/seam/async-2.2.xsd
 	 http://jboss.com/products/seam/international
		http://jboss.com/products/seam/international-2.2.xsd
 	 http://www.graniteds.org/config
		http://www.graniteds.org/public/dtd/2.2.0/granite-config-2.2.xsd">
	<core:init .../>
	...
	<!-- Flex GraniteDS -->
	<graniteds:flex-filter url-pattern="/graniteamf/*" tide="true"/>
</components>

10、27、28、31、32行为新增


5. 新建/WEB-INF/flex/services-config.xml文件,全部内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<services-config>
	<services>
		<service id="granite-service" 
			class="flex.messaging.services.RemotingService" 
			messageTypes="flex.messaging.messages.RemotingMessage">
			<destination id="person">
				<channels>
					<channel ref="my-graniteamf"/>
				</channels>
				<properties>
					<factory>seamFactory</factory>
				</properties>
	        </destination>
	    </service>
	</services>
	
	<factories>
		<factory id="seamFactory" class="org.granite.seam.SeamServiceFactory" />
	</factories>
	
	<channels>
		<channel-definition id="my-graniteamf" class="mx.messaging.channels.AMFChannel">
			<endpoint
				uri="http://{server.name}:{server.port}/{context.root}/graniteamf/amf"
				class="flex.messaging.endpoints.AMFEndpoint"/>
		</channel-definition>
	</channels>
</services-config>


6. 新建/WEB-INF/granite/granite-config.xml文件,全部内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE granite-config PUBLIC "-//Granite Data Services//DTD granite-config internal//EN" "http://www.graniteds.org/public/dtd/2.2.0/granite-config.dtd">

<granite-config>
</granite-config>


7. 以上JAVA端配置就结束了,下面创建一个测试类
import org.granite.tide.annotations.TideEnabled;
import org.jboss.seam.annotations.Name;

@Name("test")
@TideEnabled
public class Test {
	public String hello(String name) {
		return name + " 你成功了";
	}
}

@TideEnabled指明这个组件可以被Tide调用(GraniteDS使用内部Tide框架来对Seam、Spring、EJB3、CDI等进行深度集成)

配置Flex端
1. 将granite.swc、granite-essentials.swc拷贝至Flex工程的/libs目录下
   这些swc包可在刚刚下载的GraniteDS项目包的build目录下找到
   GraniteDS 2.2只需要这两个swc包就可以了,里面已经包括了tide框架及对seam的扩展。
   (GraniteDS 1.1时有一个单独的tide.swc包,现在已经不需要了。)

2.创建Test.mxml
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
			   xmlns:s="library://ns.adobe.com/flex/spark"
			   preinitialize="Seam.getInstance().initApplication()">
	<fx:Declarations>
		
	</fx:Declarations>
	
	<fx:Script>
		<![CDATA[
			import mx.controls.Alert;
			
			import org.granite.tide.events.TideFaultEvent;
			import org.granite.tide.events.TideResultEvent;
			import org.granite.tide.seam.Seam;
			import org.granite.tide.service.DefaultServiceInitializer;
			
			private function helloResult(event:TideResultEvent):void {
				Alert.show(event.result.toString());
			}
			
			private function helloFault(event:TideFaultEvent):void {
				Alert.show(event.fault.toString());
			}
			
			Seam.getInstance().addComponentWithFactory("serviceInitializer", DefaultServiceInitializer, {contextRoot: ""});
			
			[In("test")]
			public var remoting:Object;
		]]>
	</fx:Script>
	
	<s:Button label="测试" click="remoting.hello('小伙', helloResult, helloFault);" />
</s:Application>

* preinitialize="Seam.getInstance().initApplication()"
  初始化seam环境,如果想用[In]等的功能,一定要提前初始化。
* Seam.getInstance().addComponentWithFactory("serviceInitializer", DefaultServiceInitializer, {contextRoot: ""});
  设置seam环境,{contextRoot: ""}参数表示"项目上下文目录"根据实际情况设置。
* [In("test")]
  大家已经很亲切吧,就不详细介绍了。