[Solved] Serializer complains that UUID doesn't have access to default constructor?

I’m here again, producing weird issues. I’ve been playing with the Networking part of jMonkeyEngine, and I am just getting into messaging. I’m trying to do simple things.

I have a PlayerMessage which will send the Username and UUID for a Player to be created on the server (mock testing for now). Anyways, the PlayerMessage class follows.

@Serializable
public class PlayerMessage extends AbstractMessage {
        // String username; UUID uuid;
	public PlayerMessage() {
	}

	public PlayerMessage(String username, UUID uuid) {
		this.username = username;
		this.uuid = uuid;
	}
        // getters below.
}

I created my Helper class to help handle registering my Messages, and the error is thrown at the following line, with the error following.

Note: I have seen it said that you need to do this on both the Client and the Server, so in both applications I registered this in the main method. Both applications are throwing the same error.

Serializer.registerClass(PlayerMessage.class); // SerializerClassRegistration.java:11

Error

Registration error: no-argument constructor not found on:class java.util.UUID
	at com.jme3.network.serializing.serializers.FieldSerializer.checkClass(FieldSerializer.java:57)
	at com.jme3.network.serializing.serializers.FieldSerializer.initialize(FieldSerializer.java:63)
	at com.jme3.network.serializing.Serializer.registerClassForId(Serializer.java:179)
	at com.jme3.network.serializing.Serializer.registerClass(Serializer.java:273)
	at com.jme3.network.serializing.Serializer.getSerializerRegistration(Serializer.java:326)
	at com.jme3.network.serializing.Serializer.getSerializer(Serializer.java:285)
	at com.jme3.network.serializing.serializers.FieldSerializer.initialize(FieldSerializer.java:97)
	at com.jme3.network.serializing.Serializer.registerClassForId(Serializer.java:179)
	at com.jme3.network.serializing.Serializer.registerClass(Serializer.java:207)
	at com.jme3.network.serializing.Serializer.registerClass(Serializer.java:148)
	at ecrosogames.hermit.server.SerializerClassRegistration.register(SerializerClassRegistration.java:11)
	at ecrosogames.hermit.HermitApplication.main(HermitApplication.java:51)

This may not be enough to help with the general cause, so here is some more code that deals with Server/Client code that I feel may be helpful.

ClientMessageListener (followed from tutorial)

// client.addMessageListener(new ClientMessageListener());
public class ClientMessageListener implements MessageListener<Client> {

	@Override
	public void messageReceived(Client source, Message m) {
		if (m instanceof ChatMessage) {
			String msg = ((ChatMessage) m).getMessage();
			System.out.println("MESSAGE RECEIVED:\n" + msg);
		}
	}
}

ServerMessageListener (followed from tutorial)

// server.addMessageListener(new ServerMessageListener());
public class ServerMessageListener implements MessageListener<HostedConnection> {
	// ...
	@Override
	public void messageReceived(HostedConnection source, Message m) {
		if (m instanceof PlayerMessage) {
			PlayerMessage playerMessage = (PlayerMessage) m;
			String username = playerMessage.getUsername();
			UUID uuid = playerMessage.getUUID();
			Player player = new Player(null, username, uuid, source);
			hermitServer.addPlayer(player);
			hermitServer.broadcastMessage(username + " has joined.");
		}
	}
}

Sending a Message Client->Server

 // Username = "CoderMusgrove", UUID = UUID.randomUUID().
PlayerMessage playerMessage = new PlayerMessage(hermitApp.getUsername(), hermitApp.getUUID());
client.send(playerMessage);

Thank you for your time, and any help will be appreciated.

You can try using the string representation of the UUID:

  UUID.randomUUID().toString()
1 Like

That ended up working, wow. It won’t allow for the class variable to exist for it, I have to convert it in the getUUID() method.

Is there a general list of Objects that Message will accept (e.g. boolean, Number, CharSequence)?

According to the code:

protected void checkClass(Class clazz) {

    // See if the class has a public no-arg constructor
    try {
        clazz.getConstructor();
    } catch( NoSuchMethodException e ) {
        throw new RuntimeException( "Registration error: no-argument constructor not found on:" + clazz ); 
    } 
}  

Any class with a public no arg costructor should do.

If you want to use default serialization then the object must have a no-arg constructor because the default serializer instantiates it and THEN plugs fields into it.

If you really want to support UUID directly then you could always write your own Serializer for it. Then you can instantiate it however you want from the data in the buffer. If you do that, I recommend sending it as the two longs inside rather than the string representation, though… will save tons of bytes.

Here you have that serializer (you can make just copy/paste and use that class).

EDIT: Nevermind, that’s better for disk storage, it’s not great for network. However, in that link you can see how to use the two longs :wink:

Nah, your posted one in that link (from Mar 22) is exactly what I meant.

128 bits is a lot for an ID no matter what but if you need it, you need it. I suspect the number of times it’s really needed is much smaller than the number of times it’s perceived to be needed… but that’s a completely different issue. :slight_smile:

1 Like