Page 1 of 1

Base Classes and Serialization

Posted: 25 Jun 2011, 11:47
by patrickk
Hey dear Smartfox Team,
I'm currently working on an project, using Smartfox SF2X and Flash AS3 Client and got the following issue during serialization.

On client side I've the following model class:

Code: Select all

public class Person implements SerializableSFSType
	{
		public var id : int;
		public var firstName : String;
		public var lastName : String;

		public function Person()
		{
		}
	}
Javaside looks like this:

Code: Select all

@Entity
@Table(name="person")
public class Person extends PersonBase
{
	private static final long serialVersionUID = 6258734904191561262L;
}

@MappedSuperclass
public class PersonBase implements Serializable, SerializableSFSType
{
	private static final long serialVersionUID = 4812787344839070414L;

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	protected int id;

	@Column(name="firstName")
	protected String firstName;

	@Column(name="lastName")
	protected String lastName;

	...getters/setters...
}

When I send an object to the backend I got the following error:

Error deserializing request: com.smartfoxserver.v2.exceptions.SFSRuntimeException: java.lang.NoSuchFieldException: id


When I put all properties and getter/setter from the PersonBase into the Person class that works fine, but I don't want to use that code style.

So is there a way to tell the backend to look for that values when serialization/reflection takes place?

Posted: 27 Jun 2011, 16:36
by Lapo
Hi,
protected (and private) members cannot be serialized, only public ones

Posted: 07 Jul 2011, 17:50
by patrickk
Okay but when i set the visibility to public there is no error, but the values are 0 or null in the as3 client.

Posted: 08 Jul 2011, 07:57
by Lapo
Check our documentation and related examples and make sure you don't have other exceptions.
http://docs2x.smartfoxserver.com/Advanc ... ialization

Posted: 08 Jul 2011, 13:32
by patrickk
Thanks Lapo,

I've checked it again and it seems that the serialization doesn't work with inheritance.

E.g. if the 'WaterFloodSpell' would extends from a BaseSpell class which holds additional public variables, the BaseSpell variables are always null on client side.[/code]

Posted: 09 Jul 2011, 06:33
by Lapo
Correct, we'll address that in a later release

Posted: 10 Jul 2011, 12:10
by patrickk
Thanks for that information :)

Posted: 10 Dec 2011, 18:16
by silvertip
Hello Lapo,

We seem to be having the same issue. It seems properties inherited from a superclass are not serialized (on the client side we can see that the fields are not initialized and remain null).

We are using Smartfox 2X RC3.

If there is no fix yet could you please provide an estimate on when it will be rectified and suggest workarounds?

Thanks,
silvertip.

Posted: 12 Dec 2011, 10:21
by Bax
Sorry, we are not able to provide a date for the new version availability.
Also, after further analysis, it seems the requested implementation is not feasible.

Posted: 17 Dec 2011, 18:41
by silvertip
Humm that is disappointing. Smartfox is a great games server and I believe that being able to serialize properties of the base class should be a required feature, as the API is written in Java.
This means developers will tend to use inheritance. Without this feature we need to go around inheritance, so what is the point in using Java in the first instance anyway?

Also, I don't quite understand why it would not be possible to serialize the base class: don't you simply have to use reflection in order to access those fields and serialize them into bytes?

Thanks,
Silvertip.

Posted: 18 Dec 2011, 10:30
by Lapo
Let me clarify:
we don't 100% exclude supporting inheritance in the future, but there are several non-trivial technicalities that need to be addressed. (Not all API languages support strong reflection, they don't share the same inheritance rules and lots more...).

However we recommend to use composition instead of inheritance, if you know what I mean.
All you need to do is to change the thinking from Class B is a Class A to Class B has a Class A, and you can also go as deep as you wish in terms of composition depth.
Additionally composition solves the "multiple inheritance issue" in Java too

Hope it helps

Posted: 04 Feb 2012, 22:06
by harlanji
I'm having a similar problem,a lso using RC3. Basically, if I don't have a field on class I am trying to serialize, SitAction in this case, but it exists on the super class, I get an exception--note that I do have a public setter, see below.
13:55:56,791 WARN [SocketReader] protocol.SFSProtocolCodec - Error deserializing request: com.smartfoxserver.v2.exceptions.SFSRuntimeException: java.lang.NoSuchFieldException: id
If I uncomment the two lines below, then I no longer the the exception but getId() returns empty.

Code: Select all

public class SitAction extends Action implements SerializableSFSType {
  //String id;
  //Integer userId;
  String testWord;

  public SitAction() {
    super();
  }

  public String getTestWord() {
    return testWord;
  }

  public void setTestWord(String testWord) {
    this.testWord = testWord;
  }
}


public abstract class Action implements SerializableSFSType  {
  String id;
  Integer userId;

  protected Action() {
  }

  public String getId() {
    return id;
  }

  public void setId(String id) {
    this.id = id;
  }

  public Integer getUserId() {
    return userId;
  }

  public void setUserId(Integer userId) {
    this.userId = userId;
  }
}

It seems that there is some condition that is checking something like getDeclaredField("id") which will only look at the actual type (SitAction), hence that specific exception. It is possible to look at the hierarchy of types using getField("id"). Additionally, it seems like looking for a setter for the property would be an even better choice (ie. getMethod("setId")).

Regards,

Harlan

Posted: 05 Feb 2012, 09:08
by Lapo
As stated earlier we don't support inheritance

Posted: 06 Feb 2012, 20:59
by harlanji
Lapo wrote:As stated earlier we don't support inheritance
Lapo wrote:Let me clarify:
we don't 100% exclude supporting inheritance in the future
It is more the future aspect that I'm interested in, it's pretty clear that it doesn't work now. I don't see any of these 'non-trivial' problems in this case, I see simply a broken implementation. None of the details of inheritance should even matter, and properties should be deserialized to however the property is represented in the implementation doing the deserialization.

For example, if my client has some object with the properties 'id', 'name', 'speed' it shouldn't matter what the inheritance model looks like on the server, as long as it has those fields/mutators. Likewise, if it's re-broadcast out to diverse clients (for the sake of example, clients with all supported libraries), they should all be able to figure out if the target properties are on the type they are deserializing to--regardless whether it supports inheritance or not.

In my case, I am using as3 client/java server and they both happen to support inheritance, but clearly in the dump of the object over the wire there is no type information contained beyond the actual class name and the properties and values. So when it lands in my extension and I have a java class with those fields, why shouldn't I be able to deserialize?

Example:

Code: Select all

public class SomeAction {
public var id:int;
public var name:String;
public var speed:int;
}
should deserialize fine to

Code: Select all

public class SomeAction extends Action {
private int speed;
private String name;

public void setName...
public String getName...
public void setSpeed...
public int getSpeed...
}

public class Action {
private int id;

public void setId...
public int getId...
}
and vice versa. I understand this is not currently how it works, but I don't see any non-trivial or difficult problems involved in supporting it. I see a simple tweak in checking if the property exists. A) check for setter method, B) else, check for public field (using getField rather than getDeclaredField, as seems to be used now). C) if neither, property does not exist. Inheritance need not even exist, this seems like the common sense way to do it anyway.