Re: Result handler not being invoked - SOLVED
Michael Guyver <[email protected]> Wed, 7 Feb 2007 13:11:36 +0000 (UTC)
| Newsgroups | gmane.comp.java.openamf.user |
|---|---|
| Message-ID | <[email protected]> |
Michael Guyver <kenevel <at> gmail.com> writes:
Hi there,
I finally got to the bottom of this and the reason I wasn't seeing a result was
because you need to re-use the RPC envelope from the request. I was not using
the transmitted values to identify my response so I guess the NetConnection was
simply discarding it as something in which it wasn't interested. See in
particular the values below from sniffing the request/response with the Charles
HttpProxy.
I hope this helps people understand how the AMF remoting hangs together. You may
well be asking my I didn't just use the OpenAMF framework in its entirety
anyway; well, I don't want to do RPC, I want to be able to call REST-style URLs
and get a response based on those, not the serialized request. Call me old
fashioned... but I like to understand how things work.
Cheers
Mike
For completeness, here's my hacked-together code:
------------------------------------------------------------------------------
-------------------------------------------------------------------- Java code
------------------------------------------------------------------------------
package uk.co.mindfruit.flex.amf;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.openamf.AMFBody;
import org.openamf.AMFError;
import org.openamf.AMFMessage;
import org.openamf.config.CustomClassMappingConfig;
import org.openamf.config.OpenAMFConfig;
import org.openamf.io.AMFDeserializer;
import org.openamf.io.AMFSerializer;
public class DefaultAmfServlet extends HttpServlet {
protected void service(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
// initialise the custom-class mapping as I'm not using the whole gamut
// of functions from the OpenAMF project: this realy is intended as a
// proof-of-concept to get this working: AMF0, AS3, Flex 2.1 & Java
if
(OpenAMFConfig.getInstance().getCustomClassName(Person.class.getName()) == null){
CustomClassMappingConfig customClassMapping = new
CustomClassMappingConfig();
customClassMapping.setCustomClassName("guyverm.Person");
customClassMapping.setJavaClassName(Person.class.getName());
OpenAMFConfig.getInstance().addCustomClassMappingConfig(customClassMapping);
}
DataInputStream inputStream = new DataInputStream(request.getInputStream());
AMFDeserializer deserializer = new AMFDeserializer(inputStream);
AMFMessage requestMessage = deserializer.getAMFMessage();
// check target
Object serviceResult = new Person("Michael", "Guyver");
String target = getTarget(requestMessage.getBody(0), serviceResult);
// create response
AMFMessage responseMessage = new AMFMessage();
responseMessage.addBody(new AMFBody(target, "null", serviceResult));
// write output
ByteArrayOutputStream baos = new ByteArrayOutputStream();
AMFSerializer serializer = new AMFSerializer(new DataOutputStream(baos));
serializer.serializeMessage(responseMessage);
response.setContentType("application/x-amf");
response.setContentLength(baos.size());
ServletOutputStream sos = response.getOutputStream();
baos.writeTo(sos);
sos.flush();
}
private String getTarget(AMFBody requestBody, Object serviceResult) {
String target = "/onResult";
if (serviceResult instanceof AMFError) {
target = "/onStatus";
}
return requestBody.getResponse() + target;
}
}
------------------------------------------------------------------------------
--------------------------------- Charles-HttpProxy AMF request representation
------------------------------------------------------------------------------
AMFMessage Message
+---Header Array
+---Body Array
+---[0] Body Part
+---Target String doRpc()
+---Response String /1
+---Content Array
------------------------------------------------------------------------------
-------------------------------- Charles-HttpProxy AMF response representation
------------------------------------------------------------------------------
AMFMessage Message
+---Header Array
+---Body Array
+---[0] Body Part
+---Target String /1/onResult
+---Response String null
+---Content Custom Class guyverm.Person
+---firstName String Michael
+---surname String Guyver
As you can see, the request.body[0].Response is included in the
response.body[0].Target, to which the /onResult is appended. Add this and
everything starts behaving itself.
------------------------------------------------------------------------------
---------------------------------------------------------------- Action Script
------------------------------------------------------------------------------
package guyverm {
import flash.net.NetConnection;
import flash.net.ObjectEncoding;
/*
* see http://www.adobe.com/devnet/flex/articles/flex2_amfphp_03.html
*/
public class RemotingConnection extends NetConnection {
public function RemotingConnection(sURL:String) {
objectEncoding = ObjectEncoding.AMF0;
if (sURL) {
connect(sURL);
}
}
}
}
package guyverm {
public class Person {
private var myFirstName:String;
private var mySurname:String;
public function get firstName():String{
return myFirstName;
}
public function set firstName(name:String) : void {
myFirstName = name;
}
public function get surname():String {
return mySurname;
}
public function set surname(name:String) : void {
mySurname = name;
}
public function toString():String {
return myFirstName + " " + mySurname;
}
}
}
package guyverm {
import flash.display.DisplayObjectContainer;
import flash.events.NetStatusEvent;
import flash.net.Responder;
import mx.controls.TextArea;
import mx.core.IMXMLObject;
public class ErsteKlasse implements IMXMLObject {
private var displayObj:DisplayObjectContainer;
private var traceArea:TextArea;
private var gateway:RemotingConnection;
function ErsteKlasse(){
super();
}
/**
* From interface IMXMLObject.
*/
public function initialized(document:Object, id:String):void {
displayObj = (document as DisplayObjectContainer);
}
private function log(message:String):void {
if (traceArea != null){
traceArea.htmlText = traceArea.htmlText + "<br/>" + message;
}
}
flash.net.registerClassAlias( "guyverm.Person", guyverm.Person );
public function makeRemoteConnection():void {
gateway = new RemotingConnection("http://swf.localhost/flex/butt.amf");
gateway.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
gateway.call("doRpc()", new Responder(resultHandler, faultHandler));
}
public function netStatusHandler(event:NetStatusEvent):void {
log("in ErsteKlasse.netStatusHandler: event.info.code: " +
event.info.code);
}
public function resultHandler(result:Object) : void {
log("in ErsteKlasse.resultHandler: " + result);
}
public function faultHandler(message:String) : void {
log("in ErsteKlasse.faultHandler: " + message);
}
//------------------------------------------------------- MXML setters
public function set debugArea(uiComponent:TextArea):void {
traceArea = uiComponent;
}
}
}
------------------------------------------------------------------------------
------------------------------------------------------------------------- MXML
------------------------------------------------------------------------------
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns="*"
xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:guyverm="guyverm.*"
paddingTop="2"
paddingBottom="2"
paddingLeft="2"
paddingRight="2">
<mx:TextArea width="100%" height="100%" id="debugPane"></mx:TextArea>
<guyverm:ErsteKlasse
debugArea="{debugPane}"
id="serviceTarget"/>
<mx:Button label="Flex butt" click="serviceTarget.makeRemoteConnection()" />
</mx:Application>
------------------------------------------------------------------------------
---------------------------------------------------------------------- web.xml
------------------------------------------------------------------------------
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xi="http://www.w3.org/2001/XInclude"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<display-name>Flex Remoting Demo</display-name>
<servlet>
<servlet-name>amfService</servlet-name>
<servlet-class>uk.co.mindfruit.flex.amf.DefaultAmfServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>amfService</servlet-name>
<url-pattern>*.amf</url-pattern>
</servlet-mapping>
</web-app>
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier.
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642