Need some help in creating XML log in Adobe Air - actionscript-3

I need to create XML log file in Adobe Air. My first thought was to use some kind of automated serialization. And I've found FlexXB library. I've created simple logger and marked the class with annotations in the following way
package loggingTools
{
[XmlClass]
[ConstructorArg(reference="timeStamp")]
[ConstructorArg(reference="item")]
[ConstructorArg(reference="action")]
[ConstructorArg(reference="arguments")]
[ConstructorArg(reference="success")]
[Bindable]
public class MessageAction
{
[XmlAttribute()]
public var timeStamp:Date;
[XmlAttribute()]
public var item:String;
[XmlAttribute()]
public var action:String;
[XmlAttribute()]
public var arguments:String;
[XmlAttribute()]
public var success:Boolean;
public function MessageAction(timeStamp:Date, item:String, action:String, arguments:String, success:Boolean) {
this.timeStamp = timeStamp;
this.item = item;
this.action = action;
this.arguments = arguments;
this.success = success;
}
}
I'm trying to serialize the single object:
public class PlainXMLLogger
{
//private static var isStarted:Boolean;
private var logFile:XML;
[XmlArray(alias = "Log", type="loggingTools.MessageAction")]
[ArrayElementType("loggingTools.MessageAction")]
public var messages:Array;
public function addMessageAction(item:String, action:String, arguments:String, success:Boolean):void {
var newMessageAction:MessageAction;
newMessageAction = new MessageAction(new Date(), item, action, arguments, success);
messages.push(newMessageAction);
}
public function close():void {
var logXML:XML = FlexXBEngine.instance.serialize(messages);
trace(">> XML LOG ");
trace(logXML.toString() );
}
}
Now, serialization produces an error:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at com.googlecode.flexxb.core::SerializationCore/serialize()
Sure, I can serialize all objects in collection one-by-one, but I consider, that this is a bad idea.

Here is the answer on my question, provided by creators of FlexXB tool
https://groups.google.com/forum/?hl=ru&fromgroups#!topic/flexxb/g912jkxwldE

Related

Json.net contractResolver is failling

I have implemented the custom contract resolver to remove the some properties from serialized Json. Most of the time below code works but occasionally this code fails. Sometime it loops through the list and skips item I want to exclude which causing to appear that properties which I wanted to exclude.
class TestClass
{
public static void Test()
{
var objectToSerialise = //Coming from some WebAPI calls
string[] stringToSkip = {"skip1", "skip2"};
var settings = new JsonSerializerSettings
{
ContractResolver = new MyContractResolver(stringToSkip)
};
var json = JsonConvert.SerializeObject(objectToSerialise, settings);
}
}
public class MyContractResolver : DefaultContractResolver {
private string[] _skipthis;
public MyContractResolver(string[] skipthis)
{
_skipthis = skipthis;
}
private JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization){
var property = base.CreateProperty(member, memberSerialization);
property.ShouldSerialize = (prop) =>{
return !(_skipthis.Where(n => property.PropertyName.Contains(n)).Any());
};
return property;
}
}
Can someone please suggest why this code is failing silently intermittently with out throwing any kind of exception?
Note that skipthis array is not modified outside this. I want to skip the property when property name exist or substring of propertyname exist in skipthis array.

copy method of util class is not working

I am having a class Employee as:
public class Employee
{
public var name:String;
public function Employee(name:String)
{
this.name = name;
}
}
Now I am trying to create copy of an ArrayCollection of employees using ObjectUtil as:
protected function button1_clickHandler(event:MouseEvent):void
{
var newEmployees = ObjectUtil.copy(employees);
for each(var emp:Employee in newEmployees) {
Alert.show(emp.name);
}
}
But it is throwing exception:
Main Thread (Suspended: TypeError: Error #1034: Type Coercion failed:
cannot convert Object#ef41a19 to objectutil.Employee.)
objectutil::ObjectUtilCopyCheck/button1_clickHandler
objectutil::ObjectUtilCopyCheck/___ObjectUtilCopyCheck_Button1_click
Can anyone identify what is wrong here? TIA.
The method copy internally makes copy using native serialization technique:
public static function copy(value:Object):Object
{
var buffer:ByteArray = new ByteArray();
buffer.writeObject(value);
buffer.position = 0;
var result:Object = buffer.readObject();
return result;
}
If we use remoting tag then it is easy. For example:
//assume employee has [RemoteClass] metadata.
var newEmployees = Employee (ObjectUtil.copy(emp));
Else you need to register this class as (assuming that com.app.vo.Employee is the package of class Employee ):
registerClassAlias("com.app.vo.Employee",Employee);
//Now we can copy and caste
var newEmployees = Employee (ObjectUtil.copy(emp));
Hope this will help you.

Getting the Properties of NAS Datastore in vSphere Webclient SDK

In vSphere web client plugin i want to fetch the remotehost and remotepath of the datastore
I created a DataByModelRequest in the mediator class and calling one model from the mediator
[Event(name="{com.vmware.data.query.events.DataByModelRequest.REQUEST_ID}",
type="com.vmware.data.query.events.DataByModelRequest")]
private function requestData():void {
var requestInfo:DataRequestInfo = new DataRequestInfo(DataUpdateSpec.newImplicitInstance());
var dsdatarequest:DataByModelRequest = DataByModelRequest.newInstance(
_contextObject, DatastoreDataItem, requestInfo);
dispatchEvent(vmdatarequest);
}
[ResponseHandler(name=
"{com.vmware.data.query.events.DataByModelRequest.RESPONSE_ID}")]
public function onDataRetrieved(request:DataByModelRequest,
result:DatastoreDataItem, error:Error):void {
if (error != null) {
Alert.show("ERROR");
_logger.debug("onDataRetrieved error: " + error.message);
return;
}
else
Alert.show(ObjectUtil.toString(_contextObject));
Alert.show("RETRIVED");
// Assigning the result to variables to update the view.
_view.dsprop = result;
Alert.show(ObjectUtil.toString(result));
}
DatastoreDataItem is my Model Class
[Bindable]
[Model(type="Datastore")]
public class DatastoreDataItem extends DataObject {
[Model(relation="info.nas", property="type")]
public var type:String;
[Model(relation="info.nas", property="remoteHost")]
public var remotehost:String;
[Model(relation="info.nas", property="remotePath")]
public var remotepath:String;
[Model(property="url")]
public var url:String;
}
am getting the null value for all fields but name is working fine and i tried
[Model(type="NasDatastoreInfo")] also
The relational syntax you are using doesn't work because the Datastore info is not a managed entity, it's just a property field. The solution is to cast it to the right type of Datastore.Info, i.e. NasDatastoreInfo in your case. Here is the syntax to use in your model:
[Model(property="info[#type='NasDatastoreInfo'].nas.remoteHost")]
// The server for NFS datastore
public var nfsServer:String;
[Model(property="info[#type='NasDatastoreInfo'].nas.remotePath")]
// The folder for NFS datastore
public var nfsFolder:String;
Source : https://communities.vmware.com/thread/457542

Converting A plain old object to value object

I think Im having a really noob moment, Im returning a remote object from coldfusion and I want to specify the object type. i.e Im getting an worker from coldfusion and I have a Value object Worker.
Heres what I have been trying
public function ResultHandler_GetWorker(event:ResultEvent):void
{
var result:ArrayCollection = ArrayCollection(event.result);
var worker:WorkerVO = WorkerVO(result[0]);
model.worker = worker;
}
Result[0] is an employee object. Its structure from debug looks like this.
workerAddress "24b fake Ave"
workerCity "Wellton"
workerCountry "Ameriland"
workerEmail "Afake#me.com"
workerFName "Foo"
workerHPhone "435234"
workerID 1
workerImage null
workerIsAdmin true
workerLName "Foo"
workerMPhone "827271903"
workerPassword "password"
workerPosition "Leader"
workerState ""
workerSuburb "Birkenhead"
workerWPhone null
my class looks like this:
public class WorkerVO
{
public var _workerAddress:String
public var _workerCity:String
public var _workerCountry:String
public var _workerEmail:String
public var _workerFName:String
public var _workerHPhone:String
public var _workerID:uint;
public var _workerImage:String
public var _workerIsAdmin:Number;
public var _workerLName:String
public var _workerMPhone:String;
public var _workerPassword:String;
public var _workerPosition:String;
public var _workerState:String;
public var _workerSuburb:String;
public var _workerWPhone:String;
public function WorkerVO()
{
}
//Getters & Setters
}
Error #1034: Type Coercion failed: cannot convert Object#114eeb251 to com.cavej03.sitesafe.vo.WorkerVO.
Am I doing it completely wrong. Am I simply meant to make a function or constructor that accepts this object and maps its fields to a new WorkerVO
You're missing a RemoteClass metadata tag. This tag tells your application which server-side VO a given client-side VO is mapped to.
Use it like this:
[RemoteClass(alias="path.to.WorkerVO")] //this is the servers-side path
public class WorkerVO {
...
}
Furthermore from what you're showing it looks like the names of your properties don't match: the client-side one has prepended underscores while the server-side one doesn't.
The property names of the client-side VO and the server-side one should be exactly the same. For instance:
/* Java VO */
public class WorkerVO {
private String workerAddress;
public String getWorkerAddress() {
return workerAddress;
}
public void setWorkerAddress(String workerAddress) {
this.workerAddress = workerAddress;
}
}
/* ActionScript VO */
[RemoteClass(alias="path.to.WorkerVO")]
public class WorkerVO {
public var workerAddress:String;
}
This is an example with a Java VO, but the same applies to ColdFusion.
Assign the returned object to a property within WorkerVO, and prepare getters for each of them like so:
public class WorkerVO
{
private var _base:Object;
public function WorkerVO(base:Object)
{
_base = base;
}
public function get address():String{ return _base.workerAddress; }
public function get city():String{ return _base.workerCity; }
// Etc.
}
And the definition of a worker just needs the new keyword added:
var worker:WorkerVO = new WorkerVO(result[0]);
trace(worker.address);

AS3 Custom Object to ByteArray then to Custom Object

Having problem reading bytearray of custom objects. Any help is appreciated
public class CustomObject extends Object {
public function CustomObject() {
public var _x:Number = 100
public var _y:Number = 10
public var _z:Number = 60
}
}
var cObj:CustomObject = new CustomObject()
var bytes:ByteArray = new ByteArray()
bytes.writeObject(cObj)
bytes.compress()
//read
try { bytes.uncompress() } catch (e:Error) { }
var obj:CustomObject = bytes.readObject() as CustomObject
trace(obj) // null why?!
trace(obj._z) // Obviously - TypeError: Error #1009: Cannot access a property or method of a null object reference.
What you want to do is use the registerClassAlias method to register type information along with the data. That way Flash will know how to serialize/deserialize your object. Here's some sample code from Adobe's documentation:
registerClassAlias("com.example.eg", ExampleClass);
var eg1:ExampleClass = new ExampleClass();
var ba:ByteArray = new ByteArray();
ba.writeObject(eg1);
ba.position = 0;
var eg2:* = ba.readObject();
trace(eg2 is ExampleClass); // true
It should be noted that all types that should be serialized must be registered for the type information to be saved. So if you have another type that is referenced by your type, it too must be registered.
Your CustomObject class is wrong , it should throw an error actually , it should be this instead
public class CustomObject
{
public var _x:Number = 100
public var _y:Number = 10
public var _z:Number = 60
public function CustomObject()
{
}
}
Edit:
Sounds like macke has a point, because this works...
//read
try { bytes.uncompress() } catch (e:Error) { }
var obj:Object = bytes.readObject();
trace(obj) // [object Object]
trace(obj._z) // 60
Look at object that ByteArray.readObject() returns. You'll probably see that all properties are there, but type information is lost. So, you can solve this by creating some
public static function fromObject(value:Object):CustomObject {
var result:CustomObject = new CustomObject();
result._x = value._x;
//and so on...
return result;
}
To serialize custom classes to the ByteArray, you must put registerClassAlias in the constructor of the class calling the byteArray.writeObject() function.
If you don't, your custom class will be serialized as Object type. I was calling registerClassAlias in the serialize function below and my custom class keeps getting serialized as Object until I moved the registerClassAlias to the constructor.
public class MyClass{
public function MyClass(){
registerClassAlias("com.myclass", MyClass); // Ok, serializes as MyClass
serialize( new MyClass() );
}
private function serialize( _c:MyClass ){
var byteArray:ByteArray = new ByteArray();
byteArray.writeObject( _c );
//registerClassAlias("com.myclass", MyClass); Not ok, serialized as Object
EncryptedLocalStorage.setItem('key', byteArray);
}
}