Captive Imagination
September 10, 2010, 03:59:22 PM *
Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length
News: Check out the teaser site for the first official game by Captive Imagination: http://www.galaxiesbeyond.com
 
   Home   Help Search Calendar Login Register  
Pages: [1]   Go Down
  Print  
Author Topic: SharedObject fun Bugs or features ?  (Read 679 times)
0 Members and 1 Guest are viewing this topic.
Spodrum
Newbie
*
Offline Offline

Posts: 4


View Profile
« on: April 15, 2009, 10:40:48 AM »

Hi all,

I’ve been playing with JGN for sometime now and thought is was time to make a contribution.

The plan is to used SharedObjects to represent the game configuration before the host starts the game.

The SharedObject will be the screen model for the game configuration state.

I have run into some problems implementing this, some I can work around others I need advice for.

1, When a method name is supplied in the bean interface that contains upper and lower case characters (e.g selectedLevel) and this value is changed on the shard object I get a nullpointer exception. I can recreate this using just the test classes BasicSharedObjectClient / Server. It appears that the MagicBeanHandler.invoke method is supplying the method name as all lower case when trying to update the SharedObject but the method cannot be found. (SharedObjectManager beanChanged method is supplied the field as all lower case) Is this a deliberate feature or just a bug within MagicBeans ?  Work around is just to use lowercase method names for the mean time. I don’t have the source for MagicBeans as its no longer available to try out changes.

2, If the bean interface contains a collection (e.g Vector.class) a nullpointer is thrown by the CollectionConverter as the SharedObject apply method (for ObjectUpdateMessage calls converter.readObject(buffer, null); The actual CollectionConverter uses the type (supplied as null) to instantiate a collection class but fails. I tried changes this by hard coding the type from null to Vector.class and it works however this is not ideal. I can’t seem to find any way of supplying the correct class. Are only primitive type supported for SharedObjects ?

3, The plan is for a host (server who is also a client) to accept join game requests. This will allow the client into the game configuration state. The problem I have at this point is when the shared object listener is added to the client from within the game configuration state it misses the object create message as this happens when the client initially connects. I have worked around this by setting up the SharedObjectManger within the client and using SharedObjectManager.getObject() assuming that it has been created by this point within the game configuration state. Should listeners be notified of existing objects when they are added to the manager ? I think I may be missing the point a little on this one ;-)

Well that should do for my first post.
Thanks in advance for any advice / hint tips you can provide.
Cheers
Spod
Logged
darkfrog
Administrator
Inspired Imagination
*****
Offline Offline

Posts: 2650


View Profile
« Reply #1 on: April 15, 2009, 12:37:10 PM »

I’ve been playing with JGN for sometime now and thought is was time to make a contribution.

I need all the help I can get, any contributions are very appreciated. Smiley

1, When a method name is supplied in the bean interface that contains upper and lower case characters (e.g selectedLevel) and this value is changed on the shard object I get a nullpointer exception. I can recreate this using just the test classes BasicSharedObjectClient / Server. It appears that the MagicBeanHandler.invoke method is supplying the method name as all lower case when trying to update the SharedObject but the method cannot be found. (SharedObjectManager beanChanged method is supplied the field as all lower case) Is this a deliberate feature or just a bug within MagicBeans ?  Work around is just to use lowercase method names for the mean time. I don’t have the source for MagicBeans as its no longer available to try out changes.

Looks like a bug. I'll see if I can go find the source code to MagicBeans (I also have to determine what version of the API it is using) and then fix it.

2, If the bean interface contains a collection (e.g Vector.class) a nullpointer is thrown by the CollectionConverter as the SharedObject apply method (for ObjectUpdateMessage calls converter.readObject(buffer, null); The actual CollectionConverter uses the type (supplied as null) to instantiate a collection class but fails. I tried changes this by hard coding the type from null to Vector.class and it works however this is not ideal. I can’t seem to find any way of supplying the correct class. Are only primitive type supported for SharedObjects ?

Did you register Vector.class?  The JGN class should have a static method to register Vector.class before you use it so it knows how to map it across.

3, The plan is for a host (server who is also a client) to accept join game requests. This will allow the client into the game configuration state. The problem I have at this point is when the shared object listener is added to the client from within the game configuration state it misses the object create message as this happens when the client initially connects. I have worked around this by setting up the SharedObjectManger within the client and using SharedObjectManager.getObject() assuming that it has been created by this point within the game configuration state. Should listeners be notified of existing objects when they are added to the manager ? I think I may be missing the point a little on this one ;-)

Yeah, that's good point, they probably should.  I developed the SharedObject system as sort of a "neat concept" idea and never really used it for anything, so there may be quite a few bugs in the system and lacking features.  Feel free to write and submit a patch for it if you'd like to see something added or revised in it.
Logged
Spodrum
Newbie
*
Offline Offline

Posts: 4


View Profile
« Reply #2 on: April 15, 2009, 03:27:10 PM »

Thanks for the quick reply darkfrog,

Quote
Did you register Vector.class?  The JGN class should have a static method to register Vector.class before you use it so it knows how to map it across.

I have tried to register using
Code:
JGN.register(Vector.class);
on just client, just server and both at the same time with the same problem.

Here is the stack:
Code:
java.lang.NullPointerException
at com.captiveimagination.jgn.convert.Converter.newInstance(Converter.java:267)
at com.captiveimagination.jgn.convert.CollectionConverter.readObjectData(CollectionConverter.java:50)
at com.captiveimagination.jgn.convert.Converter.readObject(Converter.java:245)
at com.captiveimagination.jgn.so.SharedObject.apply(SharedObject.java:209)
at com.captiveimagination.jgn.so.SharedObjectManager.messageReceived(SharedObjectManager.java:243)
at com.captiveimagination.jgn.MessageServer.sendToListener(MessageServer.java:461)
at com.captiveimagination.jgn.MessageServer.notifyIncoming(MessageServer.java:492)
at com.captiveimagination.jgn.MessageServer.updateEvents(MessageServer.java:379)
at com.captiveimagination.jgn.MessageServer.update(MessageServer.java:662)
at com.captiveimagination.jgn.UpdatableRunnable.run(JGN.java:437)
at java.lang.Thread.run(Unknown Source)

It looks like SharedObject.apply(..) passes in null as the type and the CollectionConverter tries to create a new instance of the supplied class (null).

Code:
Object value = converter.readObject(buffer, null);
Line 209 of SharedObject.java.

I tried to see if the collection type is available at this point but it does not look like it is. Am I making a newbie mistake here? Bearing in mind I have gone back to baiscs and am using just the test classes to recreate the problem.

Quote
Yeah, that's good point, they probably should.  I developed the SharedObject system as sort of a "neat concept" idea and never really used it for anything, so there may be quite a few bugs in the system and lacking features.  Feel free to write and submit a patch for it if you'd like to see something added or revised in it.

I'll have a look at this and see if there is anything that might be useful to the project.
Logged
darkfrog
Administrator
Inspired Imagination
*****
Offline Offline

Posts: 2650


View Profile
« Reply #3 on: April 15, 2009, 07:50:57 PM »

Just to verify would you mind changing Vector to ArrayList and see if that makes a difference?
Logged
Spodrum
Newbie
*
Offline Offline

Posts: 4


View Profile
« Reply #4 on: April 16, 2009, 03:46:25 AM »

Yeah I get the same problem with ArrayList’s.
I should have mentioned that the server starts normally and it’s the client that throws the NPE.

I am unable to attach the modified versions of the JGN test classes that recreate the problem. Below is the code. Modified lines are marked with //Spodrum. Its pretty straight forward though.

MySharedBean.java:
Code:
public interface MySharedBean {
public String getOne();

public void setOne(String one);

public int getTwo();

public void setTwo(int two);

public String getSelectedlevel();

public void setSelectedlevel(String level);

public ArrayList getList(); //Spodrum

public void setList(ArrayList list); //Spodrum

}

BasicSharedObjectServer.java
Code:
public class BasicSharedObjectServer {
public static void main(String[] args) throws Exception {

JGN.register(ArrayList.class); //Spodrum

InetSocketAddress server1Address = new InetSocketAddress(InetAddress.getLocalHost(), 1000);
// Create the server
MessageServer server = new TCPMessageServer(server1Address);
//server.addMessageListener(new DebugListener("Server"));
// Create a single thread managing updates for the server and the SharedObjectManager
JGN.createThread(server, SharedObjectManager.getInstance()).start();

// Add a listener to see changes
SharedObjectManager.getInstance().addListener(new SharedObjectListener() {
public void changed(String name, Object object, String field, MessageClient client) {
System.out.println("Changed: " + name + ", " + object + ", " + field + ", " + client);
}

public void created(String name, Object object, MessageClient client) {
System.out.println("Created: " + name + ", " + object + ", " + client);
}

public void removed(String name, Object object, MessageClient client) {
System.out.println("Removed: " + name + ", " + object + ", " + client);
}
});

// Create our shared bean
MySharedBean bean = SharedObjectManager.getInstance().createSharedBean("MyBean", MySharedBean.class);
// Set a value that should be sent
bean.setOne("This is set right after the bean was created");
bean.setSelectedlevel("Test");

ArrayList list = new ArrayList(); //Spodrum
list.add("Test"); //Spodrum
bean.setList(list); //Spodrum

//bean.getVector().add("Test2");

// Enable sharing on the server so it can comprehend events
SharedObjectManager.getInstance().enable(server);
// Register it in the server so changes get broadcast to all connections when changes are made
SharedObjectManager.getInstance().addShare(bean, server);
}

BasicSharedObjectClient.java:
Code:
public class BasicSharedObjectClient {
public static void main(String[] args) throws Exception {

JGN.register(ArrayList.class); //Spodrum

// Create the server
MessageServer server = new TCPMessageServer(new InetSocketAddress(InetAddress.getLocalHost(), 2000));
//server.addMessageListener(new DebugListener("Client"));
// Create a single thread managing updates for the server and the SharedObjectManager
JGN.createThread(server, SharedObjectManager.getInstance()).start();

// Add a listener to see changes
SharedObjectManager.getInstance().addListener(new SharedObjectListener() {
public void changed(String name, Object object, String field, MessageClient client) {
System.out.println("Changed: " + name + ", " + object + ", " + field + ", " + client);
}

public void created(String name, Object object, MessageClient client) {
System.out.println("Created: " + name + ", " + object + ", " + client);
}

public void removed(String name, Object object, MessageClient client) {
System.out.println("Removed: " + name + ", " + object + ", " + client);
}
});

// Enable sharing on the server so it can comprehend events
SharedObjectManager.getInstance().enable(server);

// Connect to the server
MessageClient client = server.connectAndWait(new InetSocketAddress(InetAddress.getLocalHost(), 1000), 5000);
if (client != null) {
System.out.println("Connected!");
Thread.sleep(5000);
MySharedBean bean = (MySharedBean)SharedObjectManager.getInstance().getObject("MyBean");
System.out.println("Remote Bean Value: " + bean.getOne());
bean.setTwo(53);
} else {
System.out.println("Unable to connect!");
}
}
}

I also found http://forum.captiveimagination.com/index.php/topic,268.15.html It looked like a similar issue but didn’t seem to have been resolved. Perhaps forgotten once ScarFreewill’s project moved on.
Logged
darkfrog
Administrator
Inspired Imagination
*****
Offline Offline

Posts: 2650


View Profile
« Reply #5 on: April 16, 2009, 09:20:34 AM »

Hmmm...do the test cases that use Objects still work?
Logged
Spodrum
Newbie
*
Offline Offline

Posts: 4


View Profile
« Reply #6 on: April 16, 2009, 12:32:46 PM »

The swing shared object test classes still work.

I have created another test which uses a TestObject that implemented Serlizable and wraps an array list.

This TestObject was registered with JGN and added to the bean interface. This worked and I could access the array list on both the client and server via the wrapper.

To trigger the sync of shared objects the TestObject needed to be set into the shared bean. Adding objects to a reference of the list did not trigger an update.

I think I should be able to use it this way (using a wrapper object) to get going, was this the intended use ? I'm still usure how to fix the problem but will have a bit more of a play with it tomorrow.

Any ideas ?
Logged
Pages: [1]   Go Up
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.11 | SMF © 2006-2009, Simple Machines LLC Valid XHTML 1.0! Valid CSS!
Page created in 0.228 seconds with 20 queries.