ReferenceError using XIFF as a library to JavaScript under Adobe Air

Hello all!

I am completely new to Flash/Flex/Actionscript development (and to XMPP for that matter). Given that I’m so new to this all, I’ll try to post as much background and description as to what I’ve done so far so that if I’ve made any mistakes early on the more experienced among you might be able to help me in tracking things down faster.

First my problem description: I am developing an HTML/JS application under Adobe Air and I would like to have the ability for different instances of my application (on different machines) to communicate with each other via XMPP.

I’ve started by obtaining the XIFF source from the SVN trunk @ http://svn.igniterealtime.org/svn/repos/xiff/trunk/src

I then downloaded the Flex 3 SDK and created a flex-config xml file with a class entry for each Actionscript file and a path-element entry for airglobal.swc, framework.swc and rpc.swc. I was then able to compile XIFF using the command: acompc -load-config XIFF.xml -output XIFF.swc

As I was not able to figure out if Air could reference SWC files, I extracted the library.swf file out of XIFF.swc and renamed it to xiff.swf. I then took that xiff.swf file and added it to the folder lib/xiff/ in my Air application along with extracted SWF versions of framework and rpc. Then, in the HTML of my app, I have script tags for each of these:

    <script type="application/x-shockwave-flash" src="lib/XIFF/rpc.swf"></script>       
    <script type="application/x-shockwave-flash" src="lib/XIFF/xiff.swf"></script>

I then created a javascript file where I first created aliases as you find in AirAliases.js:

var xiff;
if (window.runtime) {
if (!xiff) xiff = {};
xiff.Anonymous = window.runtime.org.jivesoftware.xiff.auth.Anonymous;
xiff.External = window.runtime.org.jivesoftware.xiff.auth.External;

}

This is followed by my creating a JavaScript object named XMPPClient to wrapper the XIFF calls. The bulk of the object is as follows (full file is also attached):

function XMPPClient(){
this.connection;
this.server;
this.port=5222;
this.resourceName=‘air’;
this.user;
this.keepAlive;
this.presence;
this.escapedJID;
this.unescapedJID;

    this.initConnection = function(){
        this.connection = new xiff.XMPPSocketConnection();

this.connection.addEventListener(xiff.ConnectionSuccessEvent.CONNECT_SUCCESS, this.onConnectSuccess);
this.connection.addEventListener(xiff.DisconnectionEvent.DISCONNECT, this.onDisconnect);
this.connection.addEventListener(xiff.XIFFErrorEvent.XIFF_ERROR, this.onXiffError);
this.connection.addEventListener(xiff.LoginEvent.LOGIN, this.onLogin);
this.connection.addEventListener(xiff.MessageEvent.MESSAGE, this.onMessage);
this.connection.addEventListener(xiff.PresenceEvent.PRESENCE, this.onPresence);
this.connection.addEventListener(xiff.ChangePasswordSuccessEvent.PASSWORD_SUCCE SS, this.onChangePasswordSuccess);
this.connection.addEventListener(xiff.IncomingDataEvent.INCOMING_DATA, this.onIncomingData);
this.connection.addEventListener(xiff.OutgoingDataEvent.OUTGOING_DATA, this.onOutgoingData);
this.connection.addEventListener(xiff.RegistrationSuccessEvent.REGISTRATION_SUC CESS, this.onRegistrationSuccess);
}

    this.connectAndLogIn = function(srv,prt,uid,pass) {
        if(!this.connection) {
            this.initConnection();
        }
        this.server=srv;
        this.port=prt;
        this.user=uid;
        this.escapedJID = new xiff.EscapedJID(this.user);
        this.unescapedJID = new xiff.UnescapedJID(this.user);
       
        this.connection.useAnonymousLogin = false;
        this.connection.username = this.user;
        this.connection.password = pass;
        this.connection.server = this.server;
        this.connection.port = this.port;
        this.connection.resource = this.resourceName;

this.connection.connect(“standard”);

        this.keepAlive = new air.Timer(100000);
        this.keepAlive.addEventListener(air.TimerEvent.TIMER, this.onKeepAliveLoop);
        this.keepAlive.start();

}

// Each of the listeners is basically only an air.trace with the event name and printing out the data if any is available.

}

So from my main application, for example, I make a call like this:

var xmppclient = new XMPPClient();
xmppclient.connectAndLogIn(“localhost”, 5222, “user1@localhost”, “passone”);

When I am calling this to my local host running a copy of openfire, I get the following error (full log attached as openfire.txt):

ReferenceError: Can’t find variable: connection
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at org.jivesoftware.xiff.core::XMPPConnection/handleSessionResponse()[C:\Flash\Fla shDevelopWS\XIFF\src\org\jivesoftware\xiff\core\XMPPConnection.as:993]
at org.jivesoftware.xiff.core::XMPPConnection/handleIQ()[C:\Flash\FlashDevelopWS\X IFF\src\org\jivesoftware\xiff\core\XMPPConnection.as:769]
at org.jivesoftware.xiff.core::XMPPSocketConnection/bSocketReceivedData()[C:\Flash \FlashDevelopWS\XIFF\src\org\jivesoftware\xiff\core\XMPPSocketConnection.as:201]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at org.jivesoftware.xiff.util::SocketConn/onSockRead()[C:\Flash\FlashDevelopWS\XIF F\src\org\jivesoftware\xiff\util\SocketConn.as:57]
at org.jivesoftware.xiff.util::SocketConn/onRead()[C:\Flash\FlashDevelopWS\XIFF\sr c\org\jivesoftware\xiff\util\SocketConn.as:44]

The variable named “connection” is my javascript variable holding the XMPPSocketConnection. I’ve verified this by renaming the variable to “conn” and then the error message indicates the variable named “conn”.

When I am calling this to my hosting provider’s Jabber server (I am using DreamHost and I think they use jabberd), I used to get a similar error to the above, but this occurred during the onConnectSuccess event. I now have a different problem, I never get any onLogin event. I’ve also attached a log of this as dreamhost.txt.

When I was getting the error during onConnectSuccess for DreamHost and during onLogin for OpenFire, I was wondering if there was some problem propagating the events to the javascript, but that does not seem to be the case for onIncomingData or onOutgoingData. If this is the case, and the problem is just intermittent, do I need to write a wrapper to XIFF in actionscript so the connection is managed in actionscript and the javascript calls are only to pass messages or listen for events?

Any help or guidance that anyone could provide would be greatly appreciated.

Thank you very much,

Peter Richards
xmppclient.js (13628 Bytes)
openfire.txt (6055 Bytes)
dreamhost.txt (697 Bytes)

Well, I have seemingly resovled my own issue and I wanted to post here to provide my update.

I changed the model such that XIFF is compiled to a library (XIFF.swc) and I have created a new Actionscript project with a single class to act as a wrapper / interface to the XIFF library. In my air app, I deploy the XIFF.swc and the wrapper swf files in the same directory and add the script tag for the SWF into my HTML page. Then, the wrapper is accessible via javascript and can call the methods in the wrapper which actually maintains the XIFF connection object. This certainly feels like a better way of assembling the pieces (I’m learning as I go here ).

This works great with the openfire server locally, however it appears that the DreamHost jabber server is an old version that does not support stream:features.., but I’ll open a new question on dealing with that situation with XIFF if I don’t find something after a bit more digging.

Thanks,

Peter Richards