Why is my class not recognized? - apache-flex

When I try to run the following mxml file using Flexbuilder, I get the error message
1046: Type was not found or was not a compile-time constant: AlertDataObject.
This code is from the main.mxml file
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical"
horizontalAlign="center"
verticalAlign="middle"
xmlns:components="components.*"
xmlns:ConferenceRequestForm="components.core.ConferenceRequestForm.*"
xmlns:ConferenceHomeScreen="components.core.ConferenceHomeScreen.*"
xmlns:ConferenceLoginForm="components.core.ConferenceLoginForm.*"
xmlns:debug="components.debug.*"
xmlns:RandomUserMaker="components.debug.RandomUserMaker.*"
xmlns:RandomConferenceMaker="components.debug.RandomConferenceMaker.*"
initialize="initializeApplication();"
creationComplete="openConferenceHomeScreen();">
<mx:Script>
<![CDATA[
import flash.events.MouseEvent;
public function debugButtonHandler(event:MouseEvent):void{
userCredentials.logIn('admin', 'admin', "John", "Admin", 7, 99,0)
openReportsForm();
}
]]>
</mx:Script>
<mx:Button label="Debug Button" id="debugButton_btn" click="debugButtonHandler(event);" enabled="true" visible="false"/>
<RandomConferenceMaker:RandomConferenceMaker id="rcm" visible="false"/>
<RandomUserMaker:RandomUserMaker id="rum" visible="false"/>
<mx:Script source="../classes/ConferenceApp_action.as"/>
</mx:Application>
This is the top of the ConferenceApp_action.as file, which contains most of the application logic, including the Import to the class that is defining the class that is failing AlertDataObject.
//Built-In Classes
import mx.managers.PopUpManager;
//events
import mx.events.CloseEvent;
//custom events
import classes.AlertDataObject;
This is the line in the ConferenceApp_action.as file that is creating the error.
private function showChoiceWindow(data:AlertDataObject):void{
.
.
.
}
This is the AlertDataObject class.
package classes
{
public class AlertDataObject
{
/****************
Constants
****************/
static public var TITLE_ALERT:String = "Alert";
static public var TITLE_CONFIRM:String = "Please Confirm";
static public var TITLE_DEBUG:String = "Debug";
static public var TITLE_SUCCESS:String = "Success";
static public var TITLE_FAILURE:String = "Failure";
static public var TITLE_ERROR:String = "Error";
/****************
Properties
****************/
private var __title:String;
private var __text:String;
.
.
/****************
Getters / Setters
****************/
public function get title():String{
return __title;
}
.
.
.
/****************
Constructor
****************/
public function AlertDataObject($text:String, $title:String="Alert", $yesFunction:Function=null, $yesFunctionArguments:Object=null, $noFunction:Function=null, $noFunctionArguments:Object=null, $dataProvider:Object=null, $icon:Class=null){
//store basic props
__title = $title;
__text = $text;
//store confirm props
__yesFunction = $yesFunction;
__yesFunctionArguments = $yesFunctionArguments;
__noFunction = $noFunction;
__noFunctionArguments = $noFunctionArguments;
//store dataProvider object
__dataProvider = $dataProvider;
//store misc. props
__icon = $icon;
}
}
}
Why does Flex not see the AlertDataObject class properly?

I'm guessing from the way you import the ConferenceApp_action.as file that the classes directory which contains the AlertDataObject class is stored in the root directory of your project. If this is the case, try moving the classes folder to the src directory in which the main.mxml file was created. By default this is the main source folder for projects setup using Flex Builder and the place the compiler looks for custom classes.
Note that you can change the default source folder or specify an additional source folder under the flex build path options in the project properties dialogue, but in your case I don't think you need to do either of these.

I would be willing to bet that you have a syntax error either in your ConferenceApp_Action.as file or in your main.mxml file that is preventing things from completely compiling. Essentially what you're doing is an "include" rather than using a proper Class, and you don't get very good error messages when you do this. Possibly because the Flex team forgot that they left the door open for people to do this (which isn't a great practice).
IMO, you're lucky you got any kind of compile errors at all. I once inherited a project that used these types of includes where the developer forgot to add some of the files into version control. I didn't get error message one--it simply silently failed to compile.
My advice is use at least decent OOP of the type the Flex team had in mind (in other words proper Class files), and get the full weight of the compiler helping you. Failing that, try moving your script tag that points to your .as file above the other script tag. Or even making sure that all of your import statements are in the same script block.
FWIW, I believe there are some variables starting with "$" in the bowels of the Flex Framework, and the meaning of this prefix is "these are the original variables/methods defined by the Flash Player which we are pushing to the background and overwriting with our own version." I don't think that's your intent, looking at your code but if it is there is nothing wrong with leaving your variables named that way.

Nowhere in the code you've provided are you actually instantiating the AlertDataObject class. Because of that, the compiler doesn't compile it, and you don't see it at runtime. Another thing that may cause problems is using PHP coding conventions when working with actionscript. I don't think I've ever tried to start my variable names with a '$', but at the very least it goes against all good actionscript practices, and at the most, it might cause the strange runtime issues you're experiencing.

Related

How do i read embedded bytarray file?

I created a tile map editor for my game and it will generate a file when the user is done with the design. The file will store the assets used and other information.
this is the code on how i generate the file
var ba:ByteArray = new ByteArray();
var masterData:Object = { map:Data.instance.mapLayerArr,
asset:assetCollection,
gridrow:Data.instance.gridRow,
gridColumn: Data.instance.gridColumn,
cellWidth: Data.instance.cellWidth,
cellHeight: Data.instance.cellHeight,
assetCount: Data.instance.assetCount,
layerCount: Data.instance.layerCount,
version: Data.instance.version};
ba.writeObject(masterData);
ba.compress();
file = new FileReference();
file.save(ba, Data.instance.fileName);
problem starts when i want to embed the generated file inside my game.
this is the code in my program.
[Embed(source='../../../../res/tilemapdata/File Name', mimeType='application/octet-stream')]
public static const TileMapFile:Class;
public function TileMapLoader()
{
var byteArray:ByteArray;
byteArray = new TileMapFile();
byteArray.uncompress();
var obj:Object;
obj = byteArray.readObject();
trace(fileReference);
}
whenever i run it ends in "obj = byteArray.readObject();" and will display this error.
[Fault] exception, information=ArgumentError: Error #2173: Unable to read object in stream. The class flex.messaging.io.ArrayCollection does not implement flash.utils.IExternalizable but is aliased to an externalizable class.
You are using a strange class flex.messaging.io.ArrayCollection - try replacing all such imports with mx.collections.ArrayCollection.
Also make sure that all classes that are stored in file has [RemoteClass] metatag or they would be restored as Object instances.
A good read about the situation (adobe's official documentation): (Explicitly mapping ActionScript and Java objects)
I have experianced the same problem. General rules which help me to solve:
better to have explicitly declared metatag [RemoteClass] on your client-side actionscript classes.
collections of server-side classes (lists,arrays,etc.) easier to handle when represented client-side flash by mx.collections.ArrayCollection.
at some point you may need to explicitly declare client-side Flash class with the server-side class relationship by coding before any deserialization occures flash.net.registerClassAlias("net.acme.serverside.Foo", clientside.Foo ); otherwise your objects goes untyped as generic flash.Object after deserialization.
Check, that your ArrayCollection alias registered by this way:
import mx.collections.ArrayCollection;
...
registerClassAlias("flex.messaging.io.ArrayCollection", ArrayCollection);
instead of:
import mx.collections.ArrayCollection;
...
registerClassAlias("mx.collections.ArrayCollection", ArrayCollection);
There explanation:
http://livedocs.adobe.com/blazeds/1/javadoc/flex/messaging/io/ArrayCollection.html

Access objects instantiated in Flex app's MXML file in other AS classes

I've got an object declared and instantiated in my Flex application's singular MXML file:
public var CDN:CDNClass = new CDNClass;
I would like to access this same CDN object (and its public methods and properties) in another class declared in a separate .as file as such:
package my.vp
{
import my.media.CDNClass;
public class SyncConnectorManager
{
private function syncMessageReceived(p_evt:SyncSwfEvent):void
{
switch (p_evt.data.msgNm)
{
case "startStream" :
// Play a stream
CDN.parsePlayList(p_evt.data.msgVal);
break;
But when I try to access the public method parsePlayList in the CDN object in a method in the class defined in the .as file, I get the following error:
Access of undefined property CDN
The reason I want to do this is to break up the logic of my application into multiple AS files and have minimal MXML files, probably only one.
Thanks - any help is much appreciated. Perhaps my OOD/OOP thinking is not correct here?
IT depends on your class architecture. For your code to work, the CDNClass instance must be defined and implemented inside your SyncConnectorManager.
Generally, you can always call down into components, but should never call up
One option is to pass the instance ofCDNClass to a variable inside SyncConnectorManager. Add this variable to your SyncConnectionManager class:
public var CDN:CDNClass = new CDNClass;
And at some point do this:
syncConnectorManagerInstance.CDN = CDN;
That way both classes will have access to the same CDN instance and can call methods on it.
Yes, your OOP thinking is not correct here. You should take in mind differences between classes and instances. This line declares a filed in a current class and initiates it with an instance:
public var CDN:CDNClass = new CDNClass;
So current instance of your MXML class (you can think about it as usual AS class with some other notation) has public field. To operate with CDN instance you need something from the following:
Read the value of CDN (as far as it is public) from the instance of your MXML class. You need some reference to it for that.
The instance of your MXML class can have a reference to the instance of SyncConnectorManager and SyncConnectorManager should have a way to inject the value of CDN there. Something like:
Your class:
package my.vp
{
import my.media.CDNClass;
public class SyncConnectorManager
{
private var CDN:CDNClass;
public function SyncConnectorManager(CDN:CDNClass)
{
this.CDN = CDN;
}
private function syncMessageReceived(p_evt:SyncSwfEvent):void
{
switch (p_evt.data.msgNm)
{
case "startStream" :
// Play a stream
CDN.parsePlayList(p_evt.data.msgVal);
break;
In your case SyncConnectorManager class hasn't CDN declared (the problem of the compiler error you mentioned) and instantiated (the problem of NPE even if you just declare field).
As the bottom line I can suggest you to follow ActionScript naming and coding conventions to talk other people and team members about your code :)

External Config file in Actionscript 3

I need to be able to load external configuration files into my flex app. I've read that this is possible using embeds, so long as the mimeType is set to application/octet-stream.
package learning {
import org.flixel.*;
public class PlayState extends FlxState {
[Embed(source = "../../data/tiles.png")] private var _tiles:Class;
[Embed(source = '../../data/map.txt', mimeType = "application/octet-stream")] private var ExternalMapData:Class;
public var txt:FlxText;
public var player:FlxSprite;
override public function create():void {
bgColor = 0xffaaaaaa;
super.create();
}
override public function update():void {
super.update();
}
}
}
When I compile this using mxmlc, it compiles successfully with no errors. When I run the SWF, it loads all the Flixel menus then hangs.
If I comment out the [Embed(source = '../../data/map.txt' line, it compiles and doesn't hang.
Why is this embed causing a freeze?
Version info for mxmlc:
Adobe Flex Compiler (mxmlc)
Version 4.0.0 build 14159
EDIT
It turns out errors weren't being displayed properly, but this is what I'm getting from attempting the embed:
VerifyError: Error #1014: Class mx.core::ByteArrayAsset could not be found.
Google turns up a bunch of people with the same problem, but no apparent solution.
import mx.core.ByteArrayAsset; ByteArrayAsset
doesn't help either.
Aha! It turns out the solution was very simple - runtime shared libraries weren't being statically linked into the swf, and the path wasn't being set properly for access during runtime. The solution is simple:
Either modify flex-config to say
<static-link-runtime-shared-libraries>true</static-link-runtime-shared-libraries>
or manually pass in the parameter to mxmlc
mxmlc -static-link-runtime-shared-libraries=true -debug=true Main.swf -- Main.as
I'll answer this one with my answer to another question:
[Embed(source = "ExampleText.txt", mimeType = "application/octet-stream")]
protected var AAAAAA:Class;
var tmp:ByteArray = new AAAAAA();
var result:String = tmp.readMultiByte(tmp.bytesAvailable, tmp.endian);

Flex "Type Coercion" error when casting to interface

This is the error I am getting in the handleModuleReady function:
[Fault] exception, information=TypeError: Error #1034: Type Coercion failed:
can not convert MyModule#39b8479 to IModuleInterface.
I have an application setup and I have created modules to load at runtime in order to decrease the filesize (as most users will only ever need one of the modules).
<!-- maker.mxml -->
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns="*"
layout="absolute"
creationComplete="init(event)">
<mx:Style source="css/maker.css" />
<mx:Script>
<![CDATA[
//Modules
import mx.events.ModuleEvent;
import mx.modules.ModuleLoader;
import mx.modules.ModuleManager;
import mx.modules.IModuleInfo;
private var info:IModuleInfo;
...
private function init(e:Event):void {
info = ModuleManager.getModule("MyModule.swf");
info.addEventListener("ready", handleModuleReady);
info.addEventListener("error", handleModuleError);
info.load(ApplicationDomain.currentDomain);
}
private function handleModuleReady(moduleEvent:ModuleEvent):void {
var ichild:IModuleInterface = IModuleInterface(moduleEvent.target.factory.create());
if (ichild != null) {
//call class functions here via ichild object
}
else {
trace("Something has gone wrong.");
}
}
...
</mx:Script>
...
I have created the IModuleInterface class (IModuleInterface.as), and the MyModule.mxml file compiles without issue, but I continue to get the typecasting error despite trying a variety of potential solutions such as loading the module through ModuleLoader, ModuleManager, and most recently setting the applicationDomain.
Please tell me if you know how to fix this. The rest of the internet doesn't. Trust me, I've looked.
If relevant, the interface looks something like this.
//IModuleInterface.as
package
{
public interface IModuleInterface {
function getSomeClass():Class;
function getSomeArray():Array;
function getSomeInt():int;
}
}
First, if you want to compare ichild to null, you should use as to do the cast:
var ichild:IModuleInterface = moduleEvent.target.factory.create() as IModuleInterface;
Secondly, can you confirm that create() is returning an instance of the module (and not something that wraps it)? From the looks of your error, it is.
Assuming it is, it's possible that your package-less interface could be the problem. Put it into a package, and make sure the same interface interface is referenced by both the main application and the module.
Let me know how that goes.
I have read the question wrong
Try this:
var module :IModuleInterface = evt.module.factory.create() as IModuleInterface;

Create Plugins in Flex - loading nested SWF files

I'm trying to implement a plugin system for our application, and having a devil of a time getting SWF file which was dynamically loaded itself, load additional SWF files.
It goes something like this:
Main Application Shell loads...
---------+ Application loads...
-----------------+Plugin(s)
I have no problem getting app #1 to load app #2
However, try as I might, I cannot get app #2 to load and instantiate #3
I've tried various permutations using the ModuleManager, but this is the closest I get. When the onLoadComplete method get invoked, I can see that the SWF loaded, however the factory always returns NULL.
What is interesting is that when I extract this out in its own application, it works fine. This issue is triggered by the fact that I'm loading Plugin from a SWF that was loaded dynamically itself.
I believe this is due to the ApplicationDomain, but I cannot make heads or tails of it. I tried specifying currentDomain, new ApplicationDomain(Application.currentDomain) and new ApplicationDomain() without success.
Also, it is important to note that I cannot make reference a hard reference to the Foo class in either applications since by their nature, we will not know ahead of time what they will contain.
Googlin' around, this seems to be a fairly known problem, but I have not found a (clear) solution yet.
.
.
.
assetModule = ModuleManager.getModule("Foo.swf");
assetModule.addEventListener(ModuleEvent.READY, onLoadComplete );
assetModule.addEventListener(ModuleEvent.ERROR, onLoadError);
assetModule.load();
.
.
.
private var _pluginInstance:Plugin;
private function onLoadComplete( event:Event ):void
{
trace("module loaded");
_pluginInstance = assetModule.factory.create() as Plugin;
if( _pluginInstance )
_pluginInstance.startup();
else
Alert.show("unable to instantiate module");
}
private function onLoadError( event:Event ):void
{
Alert.show("error");
}
My Plugin looks like this:
package
{
import mx.collections.ArrayCollection;
import mx.modules.ModuleBase;
public class Plugin extends ModuleBase
public function startup():void
{
}
.
.
.
}
and
package
{
import Plugin;
import mx.modules.ModuleBase;
public class Foo extends Plugin
{
public function Foo()
{
trace("foo constructor invoked");
}
override public function startup():void
{
trace("foo started");
}
.
.
.
}
# joshtynjala is right. I found try just using Object then calling methods on it (don't cast).
var MyPlugin : Object = getPlugin();
MyPlugin.doPluginFunc();
Generally can cast between system/flex classes no problem. Don't know if putting Plugin as a runtime library would help ?
If you really want to use a common interface between your plugin and your application, your application's Plugin class must be the same as your plugin's Plugin class. To do so, they need b to be in the same ApplicationDomain.
//In an external library
public interface Plugin {}
//In your application
_pluginInstance = assetModule.factory.create() as Plugin;
...
//In your plugin
public class MyPlugin implements Plugin
The problem is, when you will compile your plugin swf, you will also compile Plugin. This is not a problem, but you need to tell your application that it's the same as his :
var loader:Loader = new Loader();
loader.addEventListener(Event.COMPLETE, onLoadComplete);
loader.load(new URLRequest("plugin.swf"), new LoaderContext(false, ApplicationDomain.currentDomain));
ApplicationDomain.currentDomain is the key here. If you refer to the docs :
Loader's own ApplicationDomain. You
use this application domain when using
ApplicationDomain.currentDomain. When
the load is complete, parent and child
can use each other's classes directly.
If the child attempts to define a
class with the same name as a class
already defined by the parent, the
parent class is used and the child
class is ignored.

Resources