# Änderung des Objekts wird nicht serialisiert



## Xeonkryptos (30. Dez 2011)

Moin Community,

ich habe erst kürzlich begonnen, die Serialisierung zu verwenden und habe bis jetzt, erste mal Testen und so, nur ein Problem. Ich habe eine Klasse User, die einen Namen und einen Status enthält. Nun kann sich der Status ändern und der Client soll dies dem Server mitteilen, damit alle anderen User auch sehen, dass der User seinen Status geändert hat.
Nun hab ich das Problem mit der Serialisierung lösen wollen und es ist für mich ein guter Ansatz, doch wenn ich zum zweiten Mal das Objekt mit derselben Referenz nur dem geänderten Status rüberschicke, kommt der neue Status beim Server nicht an. Ich weiß gerade nicht, wieso dass so ist? Ich hab mich ein bisschen informiert, doch sind die meisten Texte dahingehend zu schwammig für mich und unklar, ob Änderungen überhaupt mitgelesen werden oder nicht, sofern die Referenz die selbe ist.

Brauche Hilfe. ???:L


----------



## Marcinek (30. Dez 2011)

Code?


----------



## Xeonkryptos (30. Dez 2011)

Richtigen Code brauch ich eigentlich nicht posten oder kann ich nicht, da ich einfach nur den ObjectInputStream und ObjectOutputStream auf Client und Server verwende, die soweit connecte (normale Prozedur mit den Sockets) und bei einer Änderung das einfach ganz normal serialisieren und deserialisieren lasse, mit dem Standardserialisierer, da Strings auch "serializable" sind.

Im Code steht einfach nur: Schieb das User-Objekt zum Server und der Server liest einfach nur und prüft, ob das einkommende Objekt vom Typ User ist (Vermeidung einer ClassCastException) und mehr mach ich nicht. Nichts weltbewegendes, eigentlich.


----------



## Marcinek (30. Dez 2011)

Sorry, dann sehe ich kein Fehler.

Aber vieleicht findet sich ja jemand, anders im Forum der Lust auf raten hat.


----------



## Xeonkryptos (1. Jan 2012)

Also, da ich Zeit hatte und selbst nicht auf den Fehler komme, hab ich kein Testprogramm, aber Testklassen geschrieben, die im Grunde genau das Wiedergeben, was ich persönlich mache. Natürlich ist diese Version abgespeckt und ggf. nicht zum sofortigen Ausführen gedacht, es zeigt, aber meine Vorgehensweise und hoffentlich meinen Fehler:

Abgespeckter Client


```
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;

public class TestClient {

	private ObjectOutputStream output;
	private User user;

	public TestClient(Socket socket) throws IOException {
		OutputStream localOutput = socket.getOutputStream();
		output = new ObjectOutputStream(localOutput);
	}

	public void anyMethod() throws IOException {
		/*
		 * Davon ausgehend, dass der User hier schon geändert wurde. Einfach nur
		 * EINE Instanzvariable "status" über einen Setter bzw eine spezielle
		 * Edit-Methode, die auf den Setter intern zugreift
		 */
		output.writeObject(user);
	}
}
```

Abgespeckter Server


```
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.net.Socket;

public class TestServer {

	private ObjectInputStream input;

	public TestServer(Socket socket) throws IOException {
		InputStream localInput = socket.getInputStream();
		input = new ObjectInputStream(localInput);
	}

	public void anyMethod() throws ClassNotFoundException, IOException {
		Object obj = input.readObject();
		if (obj instanceof User) {
			/*
			 * Zur Überprüfung, da schon hier der geänderte Status stimmen muss
			 * zur Weiterverarbeitung
			 */
			System.out.println(((User) obj).getStatus());
			/*
			 * Hier kommt die Ausgabe: Nichts... Sollte aber schon ein Status
			 * stehen und hier befindet sich mein Problem
			 */
		}
	}
}
```

User-Klasse mit den Informationen der einzelnen User.


```
import java.io.Serializable;

public class User implements Serializable {

    private static final long serialVersionUID = 1756760419000304659L;
	private String name;
	private String status;
	private boolean hasStatus = false;

	public User(String name, String status) {
		setStatus(status);
		setName(name);
	}

	/**
	 * Verändert den Usernamen
	 * 
	 * @param name
	 *            Name des Users
	 */
	private void setName(String name) {
		if (name == null)
			throw new IllegalArgumentException("name == null");
		if (name.trim().isEmpty())
			throw new IllegalArgumentException("name is an empty string");
		this.name = name;
	}

	/**
	 * Ändert den Status des Users
	 * 
	 * @param status
	 *            Status
	 */
	private void setStatus(String status) {
		if (status == null || status.trim().isEmpty()) {
			this.status = "";
			hasStatus = false;
			return;
		}
		this.status = "<" + status + ">";
		hasStatus = true;
	}

	/**
	 * Gibt den Namen des Users zurück
	 * 
	 * @return Name
	 */
	public String getName() {
		return name;
	}

	/**
	 * Gibt den Status des Users zurück
	 * 
	 * @return Status
	 */
	public String getStatus() {
		return status;
	}

	/**
	 * Gibt den Status + Usernamen zurück (Darstellung des Users)
	 * 
	 * @return vollständige Userdarstellung
	 */
	public String getUser() {
		if (!hasStatus) {
			return getName();
		}
		return getName() + getStatus();
	}

	@Override
	public void editElement(Object... element) {
		if (element[0] instanceof String) {
			setStatus((String) element[0]);
		}		
	}
}
```


----------



## Xeonkryptos (2. Jan 2012)

Keiner eine Idee, wo mein Fehler liegen könnte oder woran es liegt, dass er denselben User ändert, aber am Ende des Streams unverändert ankommt?


----------



## Chumax (2. Jan 2012)

Das liegt am Caching des Object inputstream!


----------



## Xeonkryptos (2. Jan 2012)

Wie beug ich dem Cache vor? Ich finde oft nur etwas bezogen auf den ObjectOutputStream, den man einfach resetten kann, aber nichts über den InputStream oder ich bin einfach zu blind. 

Zumindest verliere ich die Verbindung, wenn ich den InputStream resette.


----------



## Empire Phoenix (2. Jan 2012)

Javadoc von den streams lesen, insbesondere den object streams wäre ein anfang


----------



## Xeonkryptos (2. Jan 2012)

Empire Phoenix hat gesagt.:


> Javadoc von den streams lesen, insbesondere den object streams wäre ein anfang



Jetzt hab ich mich mal rangesetzt und den ganzen Text gelesen, doch das einzige, was ich beim ObjectInputStream verwertbares gefunden hab, ist dies hier: 





> New objects are always allocated when deserializing, which prevents existing objects from being overwritten.


 und das hilft mir nicht viel weiter. Jetzt bin ich meinem Problem immer noch keinen Schritt näher gekommen, bzw der Lösung...

Edit: Problem gelöst. Anstatt einfach die Streams bloß mit einem Reset von "Altlasten" zu befreien, schreibe ich die Objekte nicht mit der writeObject-Methode, sondern mit der writeUnshared.


----------

