GAE平台上的 Flex+BlazeDS

来源:互联网 发布:mysql日期和时间函数 编辑:程序博客网 时间:2024/05/21 04:38

  话说近日Google App Engine终于开始了对Java的支持,让在下这个懒于学习Python的怂人,也有了一试GAE/J的可能。恰逢刚刚开始学习和接触Flex,因此有了将Flex+BlazeDS部署到GAE上的冲动,百度、谷歌了一下发现,尽管网上Flex+BlazeDS+Tomcat的配置方法已经泛滥成灾,但是在GAE/J上部署Flex特别是BlazeDS还没有动静。 
  没办法,只好自己动手,丰衣足食了。不罗嗦了,首先配置好GAE/J的开发环境,在下用的是标准的eclipse ganymede-SR2和GAE的eclipse plugin,接下来是下载安装Abobe官方提供的Flex Builder 3 Plug-in For eclipse,同时下载BlazeDS-bin待用。 
  首先建立Google的Web Application Project,然后手工往项目中添加Flex与BlazeDS需要的元素: 
  (1)将BlazeDS需要的jar文件(blazeds.war/WEB-INF/lib,共12个jar包)拷到工程的lib目录下,并添加到项目的Java Build Path下。 
  (2)然后要加入Flex BlazeDS需要的配置文件。在WEB-INF下新建一个名为flex的文件夹,将blazeds.war/WEB-INF/flex下的4个xml文件拷到该文件夹下。 
  (3)修改web.xml文件,加入Flex的配置。 
Java代码 
  1. <context-param>  
  2.     <param-name>flex.class.path</param-name>  
  3.     <param-value>/WEB-INF/flex/hotfixes,/WEB-INF/flex/jars</param-value>  
  4. </context-param>  
  5.   
  6. <!-- Http Flex Session attribute and binding listener support -->  
  7. <listener>  
  8.     <listener-class>flex.messaging.HttpFlexSession</listener-class>  
  9. </listener>  
  10.   
  11. <!-- MessageBroker Servlet -->  
  12. <servlet>  
  13.     <servlet-name>MessageBrokerServlet</servlet-name>  
  14.     <servlet-class>flex.messaging.MessageBrokerServlet</servlet-class>  
  15.     <init-param>  
  16.         <param-name>services.configuration.file</param-name>  
  17.         <param-value>/WEB-INF/flex/services-config.xml</param-value>  
  18.     </init-param>  
  19.     <init-param>  
  20.         <param-name>flex.write.path</param-name>  
  21.         <param-value>/WEB-INF/flex</param-value>  
  22.     </init-param>  
  23.     <load-on-startup>1</load-on-startup>  
  24. </servlet>  
  25.   
  26. <servlet-mapping>  
  27.     <servlet-name>MessageBrokerServlet</servlet-name>  
  28.     <url-pattern>/messagebroker/*</url-pattern>  
  29. </servlet-mapping>  

  作为一个几乎完全不懂Flex的怂人,在下在网上搜到了一个调用amf的简单例子,就马上Copy过来试试: 
引用

  1)新建一个java类:Hello.java 
Java代码 
  1. package com;  
  2. public class Hello {  
  3.     public String hello(String name){  
  4.         System.out.println("flex调用我了,真好~~~~");  
  5.         return "hello "+name;  
  6.     }  
  7. }  

  2)为flex配置这个要调用的对象,修改WEB-INF/flex下remoting-config.xml 
加入: 
Xml代码 
  1. <destination id="hello"> <properties> <source> com.Hello </source> </properties> </destination>  

  3)编写一个Flex程序 
Xml代码 
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">  
  3.     <mx:Script>  
  4.         <![CDATA[ 
  5.             import mx.rpc.events.ResultEvent; 
  6.             function gg(evnet:ResultEvent):void{ 
  7.             var ff:String = evnet.result as String; 
  8.             ggg.text = ff; 
  9.             } 
  10.             function remotingSayHello():void{ 
  11.             var sname:String = nameInput.text; 
  12.             h.hello(sname); 
  13.             } 
  14.         ]]>  
  15.     </mx:Script>  
  16.     <mx:RemoteObject destination="hello" id="h" result="gg(event)" endpoint="/messagebroker/amf" >  
  17.     </mx:RemoteObject>  
  18.     <mx:TextArea id="ggg" x="109" y="122"/>  
  19.     <mx:Button label="say hello" click="remotingSayHello();" x="144" y="193"/>  
  20.     <mx:TextInput id="nameInput" x="111" y="63"/>  
  21.     <mx:Label text="name" x="47" y="75"/>  
  22. </mx:Application>  

  满心欢喜,马上在本地调试启动Google Web Application,出现以下错误: 
Java代码 
  1. "Channel.Connect.Failed error NetConnection.Call.Failed:  
  2. HTTP: Status 500: url: 'http://localhost:8080/messagebroker/amf'"  

  控制台上打出log: 
Java代码 
  1. WARNING: /messagebroker/amf  
  2. java.lang.RuntimeException: Session support is not enabled in appengine-web.xml.To enable sessions, put true in that file. Without it, getSession() is allowed, but manipulation of sessionattributes is not.  
  3. at com.google.apphosting.utils.jetty.StubSessionManager$StubSession.throwException(StubSessionManager.java:67)  

  好吧,这是第一个挫败,修改WEB-INF/appengine-web.xml,在<appengine-web-app>下加入这句: 
Xml代码 
  1. <sessions-enabled>true</sessions-enabled>  

  重新启动调试,一切正常,amf调用成功。然后的任务就是将项目部署到Google App Engine上验证我们的应用了。由于众所周知的原因,GAE的JVM对不少Java类的访问都是有限制的,本地运行的成功并不能完全说明问题,还需要实地验证。 
  果不其然,马上就遇到了致命的错误: 
Java代码 
  1. Warning:**** MessageBrokerServlet failed to initialize due to runtime exception:   Error: java.lang.NoClassDefFoundError: Could not initialize class com.google.apphosting.runtime.security.shared.stub.java.lang.management.ManagementFactory  
  2.     at flex.management.PlatformMBeanServerLocator.getMBeanServer(PlatformMBeanServerLocator.java:38)  
  3.     at flex.management.BaseControl.register(BaseControl.java:186)  
  4.     at flex.management.runtime.AdminConsoleDisplayRegistrar.<init>(AdminConsoleDisplayRegistrar.java:40)  
  5.     at flex.management.runtime.messaging.MessageBrokerControl.<init>(MessageBrokerControl.java:85)  
  6.     at flex.messaging.MessageBroker.<init>(MessageBroker.java:269)  
  7.     at flex.messaging.config.MessagingConfiguration.createBroker(MessagingConfiguration.java:105)  
  8.     at flex.messaging.MessageBrokerServlet.init(MessageBrokerServlet.java:112)  
  9.     at org.mortbay.jetty.servlet.ServletHolder.initServlet(ServletHolder.java:433)  
  10.     at org.mortbay.jetty.servlet.ServletHolder.doStart(ServletHolder.java:256)  
  11.     at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40)  
  12.     at org.mortbay.jetty.servlet.ServletHandler.initialize(ServletHandler.java:612)  
  13.     at org.mortbay.jetty.servlet.Context.startContext(Context.java:139)  
  14.     at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1218)  
  15.     at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:500)  
  16.     at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:448)  
  17.     at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:40)  
  18.     at com.google.apphosting.runtime.jetty.AppVersionHandlerMap.createHandler(AppVersionHandlerMap.java:190)  
  19.     at com.google.apphosting.runtime.jetty.AppVersionHandlerMap.getHandler(AppVersionHandlerMap.java:167)  
  20.     at com.google.apphosting.runtime.jetty.JettyServletEngineAdapter.serviceRequest(JettyServletEngineAdapter.java:127)  
  21.     at com.google.apphosting.runtime.JavaRuntime.handleRequest(JavaRuntime.java:235)  
  22.     at com.google.apphosting.base.RuntimePb$EvaluationRuntime$6.handleBlockingRequest(RuntimePb.java:4823)  
  23.     at com.google.apphosting.base.RuntimePb$EvaluationRuntime$6.handleBlockingRequest(RuntimePb.java:4821)  
  24.     at com.google.net.rpc.impl.BlockingApplicationHandler.handleRequest(BlockingApplicationHandler.java:24)  
  25.     at com.google.net.rpc.impl.RpcUtil.runRpcInApplication(RpcUtil.java:359)  
  26.     at com.google.net.rpc.impl.Server$2.run(Server.java:820)  
  27.     at com.google.tracing.LocalTraceSpanRunnable.run(LocalTraceSpanRunnable.java:56)  
  28.     at com.google.tracing.LocalTraceSpanBuilder.internalContinueSpan(LocalTraceSpanBuilder.java:516)  
  29.     at com.google.net.rpc.impl.Server.startRpc(Server.java:775)  
  30.     at com.google.net.rpc.impl.Server.processRequest(Server.java:348)  
  31.     at com.google.net.rpc.impl.ServerConnection.messageReceived(ServerConnection.java:436)  
  32.     at com.google.net.rpc.impl.RpcConnection.parseMessages(RpcConnection.java:319)  
  33.     at com.google.net.rpc.impl.RpcConnection.dataReceived(RpcConnection.java:290)  
  34.     at com.google.net.async.Connection.handleReadEvent(Connection.java:428)  
  35.     at com.google.net.async.EventDispatcher.processNetworkEvents(EventDispatcher.java:762)  
  36.     at com.google.net.async.EventDispatcher.internalLoop(EventDispatcher.java:207)  
  37.     at com.google.net.async.EventDispatcher.loop(EventDispatcher.java:101)  
  38.     at com.google.net.rpc.RpcService.runUntilServerShutdown(RpcService.java:251)  
  39.     at com.google.apphosting.runtime.JavaRuntime$RpcRunnable.run(JavaRuntime.java:374)  
  40.     at java.lang.Thread.run(Unknown Source)  
  41. Critical:Uncaught exception from servlet  
  42. javax.servlet.UnavailableException: Initialization failed.  
  43.     at com.google.apphosting.runtime.jetty.AppVersionHandlerMap.createHandler(AppVersionHandlerMap.java:199)  
  44.     at com.google.apphosting.runtime.jetty.AppVersionHandlerMap.getHandler(AppVersionHandlerMap.java:167)  
  45.     at com.google.apphosting.runtime.jetty.JettyServletEngineAdapter.serviceRequest(JettyServletEngineAdapter.java:127)  
  46.     at com.google.apphosting.runtime.JavaRuntime.handleRequest(JavaRuntime.java:235)  
  47.     at com.google.apphosting.base.RuntimePb$EvaluationRuntime$6.handleBlockingRequest(RuntimePb.java:4823)  
  48.     at com.google.apphosting.base.RuntimePb$EvaluationRuntime$6.handleBlockingRequest(RuntimePb.java:4821)  
  49.     at com.google.net.rpc.impl.BlockingApplicationHandler.handleRequest(BlockingApplicationHandler.java:24)  
  50.     at com.google.net.rpc.impl.RpcUtil.runRpcInApplication(RpcUtil.java:359)  
  51.     at com.google.net.rpc.impl.Server$2.run(Server.java:820)  
  52.     at com.google.tracing.LocalTraceSpanRunnable.run(LocalTraceSpanRunnable.java:56)  
  53.     at com.google.tracing.LocalTraceSpanBuilder.internalContinueSpan(LocalTraceSpanBuilder.java:516)  
  54.     at com.google.net.rpc.impl.Server.startRpc(Server.java:775)  
  55.     at com.google.net.rpc.impl.Server.processRequest(Server.java:348)  
  56.     at com.google.net.rpc.impl.ServerConnection.messageReceived(ServerConnection.java:436)  
  57.     at com.google.net.rpc.impl.RpcConnection.parseMessages(RpcConnection.java:319)  
  58.     at com.google.net.rpc.impl.RpcConnection.dataReceived(RpcConnection.java:290)  
  59.     at com.google.net.async.Connection.handleReadEvent(Connection.java:428)  
  60.     at com.google.net.async.EventDispatcher.processNetworkEvents(EventDispatcher.java:762)  
  61.     at com.google.net.async.EventDispatcher.internalLoop(EventDispatcher.java:207)  
  62.     at com.google.net.async.EventDispatcher.loop(EventDispatcher.java:101)  
  63.     at com.google.net.rpc.RpcService.runUntilServerShutdown(RpcService.java:251)  
  64.     at com.google.apphosting.runtime.JavaRuntime$RpcRunnable.run(JavaRuntime.java:374)  
  65.     at java.lang.Thread.run(Unknown Source)  

Java代码 
  1. Error:flex.messaging.request.DuplicateSessionDetected  

  这两个问题:MessageBrokerServlet failed to initialize和DuplicateSession搞得在下死去活来,百思不得其解,不过幸好在一个几角旮旯发现了一篇美国人Martin的文章,原来是因为BlazeDS使用了在GAE/J白名单之外的class所导致,需要自己手工修改BlazeDS的源码并构建打成jar包以替换,逼得在下只好下载BlazeDS源码自己修改打包,具体解决方法如下: 
  (1)修改WEB-INF/flex/services-config.xml,在<system>下加入下句: 
Xml代码 
  1. <manageable>false</manageable>  

  这样你这一段的services-config.xml看起来应该是这样 
Xml代码 
  1. <system>  
  2.     <manageable>false</manageable>  
  3.     <redeploy>  
  4.         <enabled>false</enabled>  
  5.         <!--   
  6.         <watch-interval>20</watch-interval>  
  7.         <watch-file>{context.root}/WEB-INF/flex/services-config.xml</watch-file>  
  8.         <watch-file>{context.root}/WEB-INF/flex/proxy-config.xml</watch-file>  
  9.         <watch-file>{context.root}/WEB-INF/flex/remoting-config.xml</watch-file>  
  10.         <watch-file>{context.root}/WEB-INF/flex/messaging-config.xml</watch-file>  
  11.         <watch-file>{context.root}/WEB-INF/flex/data-management-config.xml</watch-file>  
  12.         <touch-file>{context.root}/WEB-INF/web.xml</touch-file>  
  13.          -->  
  14.     </redeploy>  
  15. </system>  

  这样就不受JMX的管理了(restricted by GAE)。 
  (2)替换WEB-INF/lib/flex-messaging-core.jar,下载见附件(基于blazeds-src-3.2.0.3978):   
  至此BlazeDS终于能运行于GAE/J上了,当然以上只是一个很简单的测试,在下也只是Flex新手,如有谬误敬请指正,谢谢。
  • flex-messaging-core.jar (629.3 KB)
  • 下载次数: 165

原创粉丝点击