[Solved] Kryonet fails to deserialize

I have been scratching my head for several hours as to why this simple kyronet connection isn’t working. It connects fine and sends all the keep alives, but then when I go to send a custom object over the network it spits out a deserialization error shown below:

com.esotericsoftware.kryonet.KryoNetException: Error during deserialization.
	at com.esotericsoftware.kryonet.TcpConnection.readObject(TcpConnection.java:141)
	at com.esotericsoftware.kryonet.Server.update(Server.java:198)
	at com.esotericsoftware.kryonet.Server.run(Server.java:356)
	at java.lang.Thread.run(Unknown Source)
Caused by: com.esotericsoftware.kryo.KryoException: Encountered unregistered class ID: 104
Serialization trace:
columns (com.digiturtle.warfare.server.Database)
	at com.esotericsoftware.kryo.util.DefaultClassResolver.readClass(DefaultClassResolver.java:113)
	at com.esotericsoftware.kryo.Kryo.readClass(Kryo.java:613)
	at com.esotericsoftware.kryo.serializers.FieldSerializer$ObjectField.read(FieldSerializer.java:599)
	at com.esotericsoftware.kryo.serializers.FieldSerializer.read(FieldSerializer.java:221)
	at com.esotericsoftware.kryo.Kryo.readClassAndObject(Kryo.java:735)
	at com.esotericsoftware.kryonet.KryoSerialization.read(KryoSerialization.java:58)
	at com.esotericsoftware.kryonet.TcpConnection.readObject(TcpConnection.java:139)
	... 3 more

This is my server:

final Server server = new Server();
		Log.TRACE();

		Kryo kryo = server.getKryo();
		kryo.register(Database.class);
		kryo.register(Record.class);
		kryo.register(Object.class);
		kryo.register(Class.class);
		kryo.register(ArrayList.class);
		kryo.register(RegistrationRequest.class);
		kryo.register(RegistrationResponse.class);
		kryo.register(Account.class);
//		kryo.register(String.class);

		server.start();
		server.bind(Settings.PORT);
		
		database = readObject(kryo, "database", Database.class);
		System.out.println(database.toString());
		server.addListener(new Listener() {
			
			public void connected(Connection connection) {
				System.out.println("Incoming Connection: " + connection.getID());
			}

			public void disconnected(Connection connection) {
				System.out.println("Ending Connection: " + connection.getID());
			}
			
			public void received(Connection connection, Object object) {
				System.out.println("Object from Connection " + connection.getID() + ": " + object);
				if (object instanceof RegistrationRequest) {
					// Removed response code
				}
			}
			
		});
		System.out.println("Starting up server");
//		try {
//			
//		} catch (Throwable t) {
//			System.out.println("Saving server");
//			writeObject(kryo, "database", database);
//		}
		long millis = 0, lastFrame = System.currentTimeMillis();
		while (true) {
			if (millis > 5000) {
				// Write file every five seconds
				millis -= 5000;
				writeObject(kryo, "database", database);
			}
			millis += System.currentTimeMillis() - lastFrame;
			lastFrame = System.currentTimeMillis();
		}

And here is my client code:

this.logger = logger;
		logger.log(Level.PRODUCTION, "Connecting to server");
		client = new Client();
		Log.TRACE();
		
		Kryo kryo = client.getKryo();
		kryo.register(RegistrationRequest.class);
		kryo.register(RegistrationResponse.class);
//		kryo.register(String.class);
		
		client.start();
		try {
			client.connect(5000, Settings.IP, Settings.PORT);
		} catch (IOException e) {
			logger.log(Level.ERROR, e);
		}
		client.addListener(new Listener() {
		       public void received(Connection connection, Object object) {
		    	   for (NetworkListener listener : listeners) {
		    		   listener.onObjectRecieved(object);
		    	   }
		       }
		});

When I send an instance of RegistrationRequest over the server, it crashes, and I don’t know why. Any thoughts?

Can I see your RegistrationRequest packet class?

Edit:
Actually, what is columns in that Stacktrace? It’s complaining about an unregistered class that you are supposedly sending over the network.

package com.digiturtle.warfare.common;

public class RegistrationRequest {
	
	private String username, password, passwordAgain, email, firstName, lastName;
	
	public RegistrationRequest() {
		username = password = passwordAgain = email = firstName = lastName = "";
	}

	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getPasswordAgain() {
		return passwordAgain;
	}

	public void setPasswordAgain(String passwordAgain) {
		this.passwordAgain = passwordAgain;
	}

	public String getEmail() {
		return email;
	}

	public void setEmail(String email) {
		this.email = email;
	}

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}
	
}

Columns is this:

private ArrayList<String> columns = new ArrayList<String>();

but what confuses me is that it crashes when I send a RegistrationRequest to the server, rather than when I read the serialized Database class.

Well the error doesn’t seem to be caused by the RegistrationRequest, that looks ok. The trace is saying that it can’t deserialize your columns list. Are you sending the list to your server to be read? It seems that Kryonet doesn’t have a registered version of the class which means (I assume) it has no idea how to “take it apart” (deserialize).

Edit:
Wait, so you send a RegistrationRequest. Then that request, I assume, modifies the database (adds a new user or something)? Can you show me the code where you use this columns list?

The only thing sent over the server is RegistrationRequest, and the columns list is read from a local file perfectly fine before the RegistrationRequest is sent.

EDIT:

Sure. I call:

database.insertRecord(request.getUsername(), request.getPassword(), request.getEmail(), 
								request.getFirstName(), request.getLastName(), new Account(request.getUsername()));

which calls:

public int insertRecord(Object... objects) {
		Record record = new Record(recordId++);
		int index = 0;
		for (String column : columns) {
			record.setValue(column, objects[index]);
			index++;
		}
		records.add(record);
		return record.getId();
	}

Okay, so if I split the serializer for the Database (local IO) and the one for the network, it works. I guess this means the issue is solved?

You most likely forgot to register something in that class, but glad it got solved!