Number to Long

Post here your questions about the Flash / Flex / Air API for SFS2X

Moderators: Lapo, Bax

CanOncel
Posts: 12
Joined: 20 Jul 2016, 11:18

Number to Long

Postby CanOncel » 20 Jul 2016, 11:43

Hello everybody,

I do not know the forum rules well, so this topic may be duplicated one.

Anyway, I'm working on a server(Java)-client(AS3) messaging system. In the system, there is same named variables on both side that the one on client side is defined as Number, other one is defined as long. There is a problem on converting a Number variable on client side(AS3) to float on server side(Java), and I got an error like this:

| WARN | SFSWorker:Sys:2 | v2.protocol.SFSProtocolCodec | | Error deserializing request: com.smartfoxserver.v2.exceptions.SFSRuntimeException: java.lang.IllegalArgumentException: Can not set long field Data.w to java.lang.Double

I really need to use long variable on server side, so I hope there is a way to deal with that.

If you need some additional information or code, let me know.

Thanks.
User avatar
Lapo
Site Admin
Posts: 23008
Joined: 21 Mar 2005, 09:50
Location: Italy

Re: Number to Long

Postby Lapo » 20 Jul 2016, 13:20

Hi,
we need more details to understand what is going on. The error shows some strange classes involved in the conversion:
Can not set long field Data.w to java.lang.Double

What is Data.w?

More importantly can you show the request sent from client side and, if necessary, the relative server side code that handles it?

Thanks

p.s. = you've posted two almost identical requests, I've removed one since it looks like once we solve one the other will also be fixed.
Lapo
--
gotoAndPlay()
...addicted to flash games
CanOncel
Posts: 12
Joined: 20 Jul 2016, 11:18

Re: Number to Long

Postby CanOncel » 20 Jul 2016, 13:56

Hello Lapo,

Thanks for answer. Don't worry about the duplicated post :)

Let me show you the codes.

PlayerInfo.java

Code: Select all

import com.smartfoxserver.v2.db.IDBManager;
import com.smartfoxserver.v2.entities.User;
import com.smartfoxserver.v2.entities.data.ISFSArray;
import com.smartfoxserver.v2.entities.data.ISFSObject;
import com.smartfoxserver.v2.entities.data.SFSObject;
import com.smartfoxserver.v2.extensions.SFSExtension;

public class PlayerInfo extends Message
{
   public int playerid;
   public String username;
   public String image;
   public int xp;
   public int level;
   public int loyaltyPoint;
   public int vipLevel;
   public double chip;
   public String bestHand;
   public long biggestWin;
   public int handsWon;
   public int handsPlayed;
   public int winRatio;
   public boolean isMe;
   public boolean isMyFriend;
   public int avatarid;
   public Boolean hasFriendRequest;

   public ISFSObject[] doWork(User user, SFSExtension ext)
   {
      ...code...
      this.biggestWin = res.getSFSObject(0).getLong("biggest_win");
      ...code...
      return null;
   }
}


Message.java

Code: Select all

import java.util.ArrayList;
import java.util.List;

import com.smartfoxserver.v2.db.IDBManager;
import com.smartfoxserver.v2.entities.User;
import com.smartfoxserver.v2.entities.data.ISFSArray;
import com.smartfoxserver.v2.entities.data.ISFSObject;
import com.smartfoxserver.v2.extensions.SFSExtension;
import com.smartfoxserver.v2.protocol.serialization.SerializableSFSType;

public abstract class Message implements SerializableSFSType
{
   protected List<User> userList = new ArrayList<User>();

   public abstract ISFSObject[] doWork( User user, SFSExtension ext);
   public List<User> getUserList() {
      ...code...
      return userList;
   }
   public int getRanking(SFSExtension ext,int playerid,Leader leader, int dayType)
   {
      ...code...
      return 0;
   }
   public int getFriendRanking(SFSExtension ext,int playerid,Leader leader)
   {
      ...code...
      return 0;
   }
}


PlayerInfo.as

Code: Select all

package
{
   import com.smartfoxserver.v2.protocol.serialization.SerializableSFSType;

   public class PlayerInfo implements Message, SerializableSFSType
   {
      public var playerid:int;

      public var username:String;
      public var image:String;
      public var xp:int;
      public var level:int;
      public var loyaltyPoint:int;
      public var vipLevel:int;
      public var chip:Number;
      public var bestHand:String;
      public var biggestWin:Number;
      public var handsWon:int;
      public var handsPlayed:int;
      public var winRatio:int;
      public var isMe:Boolean;
      public var isMyFriend:Boolean;
      public var avatarid:int;
      public var hasFriendRequest:Boolean;

      public function PlayerInfo(playerid:int = -1) {
         ...code...
      }

      public function apply():void {
         ...code...
      }
   }
}


The first 2 .java codes from server side, last one from client side.

The problem on the code is the variable named biggestWin which is Number in PlayerInfo.as and is long in PlayerInfo.java. (Data.x and biggestWin are same variables.)

By the way, I don't know if that changes something or not, I'm using the same code and structure on Unity(C#), and I haven't face with any problem yet.

Let me know if additional information needs.

Thanks.
User avatar
Lapo
Site Admin
Posts: 23008
Joined: 21 Mar 2005, 09:50
Location: Italy

Re: Number to Long

Postby Lapo » 20 Jul 2016, 15:22

How do you know the problem is with the variable biggestWin? The logs don't say and you have another variable that is of type Number, called chip which is mapped to a Double on the server side. In fact I think it's the latter that is a bit of a problem, and I'll explain why.

In AS3 there's this ambiguity where both long integer, float and double values are managed via the same "Number" type. In Java this is not the case, and each value has his type.

To resolve this ambiguity (in SFSObject.getClass/putClass) we use a "dirty trick": we check if the value passed as Number is actually an integer or decimal and use Long or Double in the SFSObject wrapping the data.

This usually works okay but there's a catch. If your double value becomes integer at runtime (e.g. = 100.0) the previously mentioned check will think that it's dealing with a Long, marks it as such but when it finally arrives to the server side it will fail to convert. (Because the relative Java class expects a Double).

Hope this clarifies the issue. As to how you could solve this... I am afraid I don't know. Usually I would recommend not using reflection-based serialization (putClass / getClass) and manage your types manually via regular SFSObject. It's one extra step in your code, but it's pretty much needed. At least in Actionscript.

Hope it helps
Lapo

--

gotoAndPlay()

...addicted to flash games
CanOncel
Posts: 12
Joined: 20 Jul 2016, 11:18

Re: Number to Long

Postby CanOncel » 21 Jul 2016, 14:06

Hello Lapo,

Thanks for helps. Under the light of the information, we thought that problem derives from serialization: Even we tried messaging with serialized classes have not any Number variables(so there is no long-double-float-int), however, still, client side(AS3) can send message, but could not take any message from server side, and even onExtensionResponse method was not triggered so that compel me to think that there is a serialization problem(I don't know if there is a way to get serialization error or something like that).

In order to help you, here is my codes:

Connector.as

Code: Select all

package
{
   import com.smartfoxserver.v2.SmartFox;
   import com.smartfoxserver.v2.core.BaseEvent;
   import com.smartfoxserver.v2.core.SFSEvent;
   import com.smartfoxserver.v2.entities.Room;
   import com.smartfoxserver.v2.entities.data.ISFSObject;
   import com.smartfoxserver.v2.entities.data.SFSObject;
   import com.smartfoxserver.v2.requests.ExtensionRequest;
   import com.smartfoxserver.v2.requests.LoginRequest;
   import com.smartfoxserver.v2.util.ConfigData;
   
   import flash.system.Capabilities;
   import flash.utils.flash_proxy;

   public class Connector
   {
      private var sfs:SmartFox;
      
      public function Connector() {
         Connect();
      }
      
      private function SendSomethingExample():void {
         var msg:Message = new PlayerInfo();
         SendMessage(msg);
      }
      
      public function Connect(accessToken:String = ""):void {
         Log.log("Connect");
         if(sfs == null){
            var cfg:ConfigData = new ConfigData();
            cfg.host = Config.SERVER_IP;
            cfg.zone = "Zone";
            cfg.port = 9933;
            
            // Initialize SFS2X
            sfs = new SmartFox();
            
            //sfs.SetReconnectionSeconds(1);
            
            sfs.addEventListener(SFSEvent.CONNECTION, OnConnection);
            sfs.addEventListener(SFSEvent.EXTENSION_RESPONSE, onExtensionResponse);
            
            sfs.addEventListener(SFSEvent.LOGIN, OnLogin);
            sfs.addEventListener(SFSEvent.LOGIN_ERROR, OnLoginError);
            
            sfs.addEventListener(SFSEvent.ROOM_JOIN, OnRoomJoin);
            sfs.addEventListener(SFSEvent.ROOM_JOIN_ERROR, OnRoomJoinError);
            
            sfs.addEventListener(SFSEvent.CONNECTION_RETRY, OnConnectionRetry);
            sfs.addEventListener(SFSEvent.CONNECTION_RESUME, OnConnectionResume);
            sfs.addEventListener(SFSEvent.CONNECTION_LOST, OnConnectionLost);
            sfs.addEventListener(SFSEvent.MODERATOR_MESSAGE, OnModeratorMessage);
            
            sfs.addEventListener(SFSEvent.PUBLIC_MESSAGE, OnPublicMessage);
            
            sfs.connect(Config.SERVER_IP, Config.SERVER_PORT);
         }
      }
      
      private function Login():void{
          var info:SFSObject = new SFSObject();
         
         if(Capabilities.manufacturer.toLowerCase().indexOf("ios")){
            info.putInt("deviceType", 2);
         }else if(Capabilities.manufacturer.toLowerCase().indexOf("android")){
            info.putInt("deviceType", 1);
         }else{
            info.putInt("deviceType", 3);
         }
         
         info.putUtfString("deviceId", Config.DEVICE_ID); //UnityEngine.Random.Range(0,1000000) SystemInfo.deviceUniqueIdentifier
         //info.putUtfString("accessToken", FB.IsLoggedIn ? Facebook.Unity.AccessToken.CurrentAccessToken.TokenString : "");
         info.putUtfString("language", Config.LANGUAGE);
         
         var request:LoginRequest = new LoginRequest("","","PokerZone", info);
         sfs.send(request);
      }
      public function JoinRoom(roomId:int):void{
         ...code...
      }
      
      public function SendMessage(message:Message):void{
         if(sfs != null && sfs.isConnected){
            var info:ISFSObject = new SFSObject();
            info.putClass("message", message);
            var request:ExtensionRequest = new ExtensionRequest("handleMessageRequest", info);
            sfs.send(request);
         }else{
            ...code...
         }
      }
      
      public function LeaveRoom():void{
         ...code...
      }
      
      // HANDLERS
      private function OnConnection(e:BaseEvent):void{
         if(e.params["success"] as Boolean){
            Login();
         }else{
            sfs = null;
            connectingCount = 0;
         }
      }
      
      private function OnLogin(e:BaseEvent):void{
         ...code...
      }
      
      private function OnModeratorMessage(e:BaseEvent):void{
         ...code...
      }
      
      private function OnRoomJoin(e:BaseEvent):void{
         ...code...
      }
      
      private function onExtensionResponse(e:SFSEvent):void{
         try
         {   
            var objIn:ISFSObject = e.params["params"] as SFSObject;
            var msg:Message;
            
            if(objIn.getClass("message") is Array){
               
               var arr:Array = objIn.getClass("message") as Array;
               
               for(var i:int = 0; i < arr.Length; i++){
                  msg = objIn.getClass("message") as Message;

                  msg.apply();
               }
            }else{
               msg = objIn.getClass("message") as Message;
               
               msg.apply();
            }
         }
         catch (ex:Error)
         {
            Log.log(ex.getStackTrace());
         } 
         
      }
      
      private function OnPublicMessage(e:BaseEvent):void{
         // TODO : Chat
      }
      
      // ERRORS
      private function OnLoginError(e:BaseEvent):void{
         ...code...
      }
      
      private function OnRoomJoinError(e:BaseEvent):void{
         ...code...
      }
      
      private function OnConnectionLost(e:BaseEvent):void{
         ...code...
      }
      private function OnConnectionRetry(e:BaseEvent):void{
         ...code...
      }
      private function OnConnectionResume(e:BaseEvent):void{
         ...code...
      }
      
      private function tryToReconnect():void{
         Connect();
      }
      private function killConn():void{
         sfs.killConnection();
      }
      
      private function Quit(action:String):void{
         ...code...
      }
   }
}


I made some changes on Message.as class.

Message.as

Code: Select all

package
{
   import com.smartfoxserver.v2.protocol.serialization.SerializableSFSType;

   public class Message implements SerializableSFSType
   {   
      public function apply():void {}
   }
}


And, here is my PlayerInfo.as

PlayerInfo.as

Code: Select all

package
{
   public class PlayerInfo extends Message
   {
      public var playerid:int;

      public var username:String;
      public var image:String;
      public var xp:int;
      public var level:int;
      public var loyaltyPoint:int;
      public var vipLevel:int;
      public var chip:Number;
      public var bestHand:String;
      public var biggestWin:Number;
      public var handsWon:int;
      public var handsPlayed:int;
      public var winRatio:int;
      public var isMe:Boolean;
      public var isMyFriend:Boolean;
      public var avatarid:int;
      public var hasFriendRequest:Boolean;

      public function PlayerInfo(playerid:int = -1) {
         ...code...
      }

      override public function apply():void {
         ...code...
      }
   }
}


Hopefully, I can express myself well.

If you need additional information, let me know.

Thanks for advices and helps.
User avatar
Lapo
Site Admin
Posts: 23008
Joined: 21 Mar 2005, 09:50
Location: Italy

Re: Number to Long

Postby Lapo » 21 Jul 2016, 14:36

CanOncel wrote:Hello Lapo,

Thanks for helps. Under the light of the information, we thought that problem derives from serialization: Even we tried messaging with serialized classes have not any Number variables(so there is no long-double-float-int), however, still, client side(AS3) can send message, but could not take any message from server side, and even onExtensionResponse method was not triggered so that compel me to think that there is a serialization problem

No, this sounds like an entirely different problem.
If you're sending data from your Extension to the client the event will trigger, unless there are other issues such as errors in your code etc... Please make sure to check your server side logs and tell us what you've found.

As a side note I've found quite strange this line in your client side code, onExtensionResponse method:

Code: Select all

if(objIn.getClass("message") is Array){
...
}

getClass returns a serializable object that must match it's corresponding Java implementation. Why do you expect it to be of type Array? Array is a native class in AS3 and it's definitely not transportable (serializable) via SmartFox API.

thanks
Lapo

--

gotoAndPlay()

...addicted to flash games
CanOncel
Posts: 12
Joined: 20 Jul 2016, 11:18

Re: Number to Long

Postby CanOncel » 22 Jul 2016, 06:16

Hello Lapo,

If we set the main problem aside, I want to ask you what is the related class of Java's Arraylist in AS3 other than Array? If we send ArrayList from Java server side, how can we handle the ArrayList in AS3 client side? In other words, what do you suggest me?

To get to the main point, I'm trying to do various things to handle/understand the main problem, I will let you know what is going on.

Thanks.
User avatar
Lapo
Site Admin
Posts: 23008
Joined: 21 Mar 2005, 09:50
Location: Italy

Re: Number to Long

Postby Lapo » 22 Jul 2016, 08:28

CanOncel wrote:If we set the main problem aside, I want to ask you what is the related class of Java's Arraylist in AS3 other than Array? If we send ArrayList from Java server side, how can we handle the ArrayList in AS3 client side? In other words, what do you suggest me?

Sure, this is correct.
Any Collection from java (such as an ArrayList) gets translated into a native Array in Actionscript.

However there are two problems with the code I have pointed out:

Code: Select all

if(objIn.getClass("message") is Array){
...
}


1) I am not sure why you need to check the type of an object at a specific key. You should already have decided what type it is in you server side code. In other words types sent from either side should be static. Maybe you're deciding the type dynamically? Why?

2) This is more important: the setClass() and getClass() methods work with objects that implement the SerializableSFSType interface. The Actionscript Array class and the Java ArrayList class do not implement this interface, so I am doubly puzzled as to why you're checking the type at runtime and why the Array type, which is not serializable directly.

To transmit an Array/ArrayList you will need to create your own custom class, implement the SerializableSFSType interface and then declare your array in there. ( which is exactly what you're doing in your Java Message class you have posted, so that is correct )

Hope it's clear
Lapo

--

gotoAndPlay()

...addicted to flash games
CanOncel
Posts: 12
Joined: 20 Jul 2016, 11:18

Re: Number to Long

Postby CanOncel » 25 Jul 2016, 07:07

Hello Lapo,

Thanks for advice. Still, I could not solve my main problem yet, but I had to postpone the problem because of some reasons, so when I come back to AS3, I will let you know the problem's process.

Thanks.
CanOncel
Posts: 12
Joined: 20 Jul 2016, 11:18

Re: Number to Long

Postby CanOncel » 26 Jul 2016, 06:20

Hello Lapo,

Still, problem continues. Let me define the problem again: Client side(AS3) can send message to server side(Java), but could not take any message from server side, even onExtensionResponse in client side was not triggered. So, first of all, I was thinking this is serialization problem but you said me it should be completely different and there must be an error. When I check server side logs, there is not any error. It means that the problem is in client side, but there is not any error logs, message either.

I need to know how I can get the error if it exists. Any additional handlers on Connector.as? Maybe a tool you know? If all the handlers in Connector.as are enough to handle, what is the possible errors here?

Thanks.
User avatar
Lapo
Site Admin
Posts: 23008
Joined: 21 Mar 2005, 09:50
Location: Italy

Re: Number to Long

Postby Lapo » 26 Jul 2016, 08:02

Hi,
CanOncel wrote:Still, problem continues. Let me define the problem again: Client side(AS3) can send message to server side(Java), but could not take any message from server side, even onExtensionResponse in client side was not triggered.

I need more details.
You start up a connection and you get the CONNECT event back with a "success" flag == true. Correct?
If this is the case then I suppose the next thing you do is sending a LoginRequest. Do you get LOGIN event back in response?

I need to know how I can get the error if it exists. Any additional handlers on Connector.as? Maybe a tool you know? If all the handlers in Connector.as are enough to handle, what is the possible errors here?

What is Connector.as?

thanks
Lapo

--

gotoAndPlay()

...addicted to flash games

Return to “SFS2X ActionScript 3 API”

Who is online

Users browsing this forum: No registered users and 22 guests