# ClassCastException bei ObjectInputStreams



## goodcat (30. Mai 2012)

Moisen,

ich habe versucht ein kleines Programm zu schreiben welches mit ObjectInputStream und ObjectOutputStream über Sockets Objekte austauscht.

Der Client und der Server liegen in 2 separaten Java Projekte. z.B. src.server.* und src.client aber in getrennten Projekten.

Nun habe ich ein Object das Übertragen werden soll (Client.java):

```
public class Client implements Serializable {

	private static final long serialVersionUID = 3142598191535415112L;
	
	private String computerName;
	private String ipAddress;
	
	public Client() {
	}
	
	public String getComputerName() {
		return computerName;
	}
	public void setComputerName(String computerName) {
		this.computerName = computerName;
	}

	public String getIpAddress() {
		return ipAddress;
	}
	public void setIpAddress(String ipAddress) {
		this.ipAddress = ipAddress;
	}

	@Override
	public String toString() {
		return this.computerName;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((computerName == null) ? 0 : computerName.hashCode());
		result = prime * result
				+ ((ipAddress == null) ? 0 : ipAddress.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Client other = (Client) obj;
		if (computerName == null) {
			if (other.computerName != null)
				return false;
		} else if (!computerName.equals(other.computerName))
			return false;
		if (ipAddress == null) {
			if (other.ipAddress != null)
				return false;
		} else if (!ipAddress.equals(other.ipAddress))
			return false;
		return true;
	}
}
```
Die gleiche Klasse mit der gleichen SerialVersionUID befindet sich im Verzeichnis des Servers.

Wenn ich jetzt auf dem Server diese Klasse instanziere und über den ObjectOutputStream senden will kommt es auf der Clientseite zu einer ClassCastException.

```
Client client = (Client) ois.readObject();
```

Wenn ich den Server und Client in das selbe Projekt kopiere und die gleiche Client.java via import einfüge klappt es. Nur sind der Server und Client getrennt und sollten auch in unterschiedlichen Projekten liegen...

Was kann ich gegen die Exception unternehmen.

Vielen Dank!


----------



## SlaterB (30. Mai 2012)

lies das Objekt zunächst in eine Object-Variable ein, dann gib dessen getClass() aus,
die Fehlermeldung klingt eher als wäre es schlicht eine andere Klasse, auch wenn das deinem erfolgreichen Test widerspricht,

bei falscher Client-Version sollte eher eine Fehlermeldung a la
> java.io.InvalidClassException: test.Client; local class incompatible: stream classdesc serialVersionUID = abc, local class serialVersionUID = xy
aber vielleicht je nach JVM anders gehandhabt, bzw. bei dir ist es ja sicherlich nicht der Fehler der abweichenden Id

dieser testweise Fehler tritt bei schon beim readObject() auf, nicht erst beim Cast,
auch in der Hinsicht wäre es wichtig, die Befehle zu trennen (nicht readObject() + Cast in derselben Zeile),
wobei ein StackTrace zur Exception auch verraten sollte ob es tief in readObjact() oder eben eher erst beim Cast passiert,
wie so üblich bei ClassCastExceptions

-----

allgemein zu gemeinsamen Klassen: wenn möglich lagere sie in dritte Projekte aus, die nicht so oft kompiliert werden,
die fertige .class-Datei, ein und dieselbe Datei, an Client + Server verteilen, dann wäre serialVersionUID nicht nötig

--------

> Wenn ich den Server und Client in das selbe Projekt kopiere und die gleiche Client.java via import einfüge klappt es. 

musst du an den imports irgendwas ändern?
gibt es zwei Client-Klassen gleichzeitig, nicht zufällig in unterschiedlichen packages?
würde allerdings auch wieder zu einer anderen Exception führen, ClassNotFoundException..


----------



## goodcat (30. Mai 2012)

Mhh ok also habe ich 2 Möglichkeiten.

1. In drittes Projekt auslagern und ein und die selbe Datei importieren.
2. Wenn ich dich richtig verstanden habe. Cast vom readObject trennen...

```
Object obj = ois.readObject();
Client client = (Client) obj;
```
getClass() müsste ich mir schenken können da im StackTrace die korrekten Klassen angezeigt wurden nur mit unterschiedlichen Pfaden. Aber werde es trotzdem mal testen.

Werde ich heute Abend mal probieren. Wenn es nicht klappen sollte würde ich den genauen StackTrace mal posten.

Bis dahin, Vielen Dank.


----------



## SlaterB (30. Mai 2012)

> getClass() müsste ich mir schenken können da im StackTrace die korrekten Klassen angezeigt wurden nur mit unterschiedlichen Pfaden.

ah, natürlich, so ergibt es Sinn (und gemein, das zu verschweigen),
wäre beim Empfänger nur eine Client-Klasse vorhanden, aber im falschen package, gäbe es ClassNotFoundException,

wenn es aber zwei Clients, in unterschiedlichen packages, gibt, wird die Klasse korrekt erkannt, 
du willst sie dann aber zu der im anderen package casten,

das ist offensichtlich nicht gut, achte streng darauf dass sie auf beiden Seiten in denselben package liegt,
mit 'drittes Projekt' wäre das eh gesichtert, dank serialVersionUID kannst du es aber auch so wie bisher getrennt machen


----------



## goodcat (30. Mai 2012)

> ah, natürlich, so ergibt es Sinn (und gemein, das zu verschweigen),
> wäre beim Empfänger nur eine Client-Klasse vorhanden, aber im falschen package, gäbe es ClassNotFoundException,
> 
> wenn es aber zwei Clients, in unterschiedlichen packages, gibt, wird die Klasse korrekt erkannt,
> du willst sie dann aber zu der im anderen package casten,



Naja zu einfach wollte ich das jetzt auch nicht machen :bae: Aber genau das könnte der Fehler sein.
Die Client Klasse im Serverprojekt liegt in einem anderen Package als die Client Klasse im Clientprojekt.
D.h. beide Klassen müssen vom Namen her im gleichen Package liegen... Mh wird schwierig... wie umständlich ist das denn bitte 

Ich glaub das mit dem dritten Projekt wird immer interessanter ... Blöde frage aber wie kann ich die Klasse aus dem dritten Projekt importieren? Muss ich ne Jar File draus machen und in den Classpath laden?


----------



## nillehammer (30. Mai 2012)

> Muss ich ne Jar File draus machen und in den Classpath laden?


Ja, genau so. Beim Entwickeln kannst Du in der IDE meist das dritte Projekt direkt im Build-Path der anderen beiden verlinken. So werden Änderungen im dritten Projekt sofort in den anderen beiden Projekten verfügbar, ohne den Umweg "Jar Bauen". Sber in der Laufzeitumgebung muss das JAR in den Classpath.


----------



## goodcat (1. Jun 2012)

Jau hat wunderbar funktioniert!!
Vielen Dank euch beiden!


----------

