# Netty von JBoss



## borobudur (19. Okt 2010)

Hallo,
ich verstehe nicht ganz wie Netty funktioniert. 

Ist es korrekt, dass man nur primitive typen übers netz schicken kann und dazu noch den byte wert angeben muss?

Wenn ich mir das POJO beispeil anschaue, dann wird da beim Encoder/Decoder der integer wert in ein byte-buffer geschrieben und abgeschickt:

```
public class TimeEncoder extends SimpleChannelHandler {
	public void writeRequested(ChannelHandlerContext ctx, MessageEvent e) {
		UnixTime time = (UnixTime) e.getMessage();
		ChannelBuffer buf = buffer(4);
		buf.writeInt(time.getValue());
		Channels.write(ctx, e.getFuture(), buf);
	}
}
```
Auf der anderen seite wieder neu initialisiert:

```
public class TimeDecoder extends FrameDecoder {

	@Override
	protected Object decode(ChannelHandlerContext ctx, Channel channel,
			ChannelBuffer buffer) throws Exception {
		if (buffer.readableBytes() < 4) {
			return null;
		}
		return new UnixTime(buffer.readInt());
	}

}
```
Was ist jetzt, wenn ich ein komplexeres objekt verschicken will? 
Geht das nicht komfortabler??


----------



## FArt (20. Okt 2010)

Es geht genau so komfortabel wie hier ausführlichst beschrieben: The Netty Project 3.2 User Guide

Du musst bedenken, dass diese API noch sehr lowlevel ist, d.h. sie ist knapp über den reinen Sockets anzusiedeln. Wenn dir das zu "unkomfortabel" erscheint, hast du vermutlich die falsche API für dein Problem gewählt.


----------



## borobudur (20. Okt 2010)

FArt hat gesagt.:


> Du musst bedenken, dass diese API noch sehr lowlevel ist, d.h. sie ist knapp über den reinen Sockets anzusiedeln. Wenn dir das zu "unkomfortabel" erscheint, hast du vermutlich die falsche API für dein Problem gewählt.


Ja, wirklich lowlevel. Auf den ersten blick hätte ich mir mehr komfort erhofft.


----------



## Gast2 (20. Okt 2010)

Naja, du musst nur halt einen Enoder und Decoder für deine Objecte haben. Das wir bei größeren Objekten evtl etwas nervig - aber dann könntest du versuchen es über Serialization zu machen, also im Encoder in den byte Stream serialisieren beim decoden aus dem byte stream lesen:
Terra Java: Deep cloning of Serializable objects


----------



## borobudur (20. Okt 2010)

Warum ist denn dieser ansatz langsamer? Ich hätte erwartet, dass auf lowlevel performanz herausspringt.


----------



## Gast2 (20. Okt 2010)

Das bezieht sich in dem Artikel auf das Clonen von Objekten. Da ist der Weg [c]Object -> Bytestream schreiben ->  Bytestream lesen -> Object langsamer[/c] als ein [c]new Object[/c] und dann setzen der Membervariablen mit Setter Methoden. Über eine Netzwerkverbindung kommen ja nüchtern betrachtet nur bytes rüber - von daher hast du gar keine andere Wahl als dein Object aus den empfangenden bytes wieder aufzubauen.

Beispiel


```
public clas Test{
    private String test;
    public String getTest(){
         return test;
    }
    public String setTest(String test){
         this.test= test;
    }
    public Object clone(){
        Test clone = new Test();
         clone.setTest(this.test);
        return clone;
    }
```

Bei so einem Object würde sich klonen über die Bytestreams nicht lohnen.


----------



## borobudur (20. Okt 2010)

fassy hat gesagt.:


> Bei so einem Object würde sich klonen über die Bytestreams nicht lohnen.


Okay, alles klar!


----------



## FArt (20. Okt 2010)

borobudur hat gesagt.:


> Warum ist denn dieser ansatz langsamer? Ich hätte erwartet, dass auf lowlevel performanz herausspringt.



Nicht zwangsläufig. Netty verfolgt nicht nur den Ansatz besserer Performance sonder bietet auch eine Abstraktion und Vereinheitlichung.

Augen auf beim API-Kauf!

Was das Beispiel mit dem Deep-Clone hier soll, habe ich nicht ganz verstanden. Ich hoffe du kommst jetzt nicht auf den Trichter, deine serialisierbaren Objekte so über das Netz zu schicken...


----------



## borobudur (20. Okt 2010)

FArt hat gesagt.:


> Was das Beispiel mit dem Deep-Clone hier soll, habe ich nicht ganz verstanden. Ich hoffe du kommst jetzt nicht auf den Trichter, deine serialisierbaren Objekte so über das Netz zu schicken...


Ich versuche jena-modelle (ontologien) vom server zu einem client zu schicken. Jena bietet keine Serialisierung. Da have ich ein problem mit RMI. Was ich nun versucht habe ist folgendes:

```
public class ModelEncoder extends SimpleChannelHandler {
	public void writeRequested(ChannelHandlerContext ctx, MessageEvent e) {
		// the model to be encoded
		Model model = (Model) e.getMessage();
		// output stream
		ChannelBuffer buf = buffer(430);
		ChannelBufferOutputStream cbos = new ChannelBufferOutputStream(buf);
		// write the model to the stream
		model.write(cbos);
		// send the stream
		Channels.write(ctx, e.getFuture(), cbos.buffer());
	}
}
```
das war serverseitig, und der client empfängt das teil so:

```
public class ModelDecoder extends FrameDecoder {

	@Override
	protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
		System.out.println("readableBytes: " + buffer.readableBytes());
		
		if (buffer.readableBytes() < 430) {
			return null;
		}
		ChannelBufferInputStream cbis = new ChannelBufferInputStream(buffer);
		// read from the input stream and create a new model instance
		return (Model)ModelFactory.createDefaultModel().read(cbis, null);
	}

}
```
Ich habe aber mühe die bytes angeben zu müssen. Ein modell kann ja irgend eine grösse haben.


----------



## Gast2 (21. Okt 2010)

Da musst du dir ein eigenes Protokoll drum rum bauen. Also z.B. erst einen Header schicken der sagt wie lange der Contentteil ist was der Server dann auswerten kann.


----------



## FArt (21. Okt 2010)

fassy hat gesagt.:


> Da musst du dir ein eigenes Protokoll drum rum bauen. Also z.B. erst einen Header schicken der sagt wie lange der Contentteil ist was der Server dann auswerten kann.


Ja, zum Beispiel.



borobudur hat gesagt.:


> Ich habe aber mühe die bytes angeben zu müssen. Ein modell kann ja irgend eine grösse haben.



Ich habe zwar keine Ahnung was Jena Modelle sind, kenne aber wenige Modelle aus Jena. Ne, ok, du meinst die API ...

Du bist immer noch sicher, dass du die richtige API bzw. den richtigen Ansatz für dein Vorhaben gewählt hast?

Objekte sind nicht serialisierbar, du möchstest sie aber serialisieren. Warum sind sie nicht serialisierbar? Fehlt ihnen lediglich das Markerinterface oder hat das einen Grund? Gibt es eine andere Möglichkeit der serialisierung oder externalisierung, die von der Jena-API vorgesehen ist, z.B. Export und Import in XML?


----------



## borobudur (21. Okt 2010)

FArt hat gesagt.:


> Du bist immer noch sicher, dass du die richtige API bzw. den richtigen Ansatz für dein Vorhaben gewählt hast?


Nein, bin ich mir noch nicht.


FArt hat gesagt.:


> Objekte sind nicht serialisierbar, du möchstest sie aber serialisieren. Warum sind sie nicht serialisierbar? Fehlt ihnen lediglich das Markerinterface oder hat das einen Grund? Gibt es eine andere Möglichkeit der serialisierung oder externalisierung, die von der Jena-API vorgesehen ist, z.B. Export und Import in XML?


So wie ich das verstehe, sind Jena-modelle zu komplex um das java-serializable-interface zu implementieren. Ein entwicker von jena hat geschrieben:
	
	
	
	





```
Serialising a Model using Java serialsation will mean serialising most (if not all) of the .model.impl.* classes, and the Graph classes - eight kinds of nodes, several descendants of GraphBase, PrefixMappings, QueryHandlers, etc ad nauseum.
```
Die empfohlene lösung hier ist via i.o.-operationen das modell zu serialisieren in, bspw., RDF/XML. Das teste ich zur zeit. Da würde Netty doch ganz gut passen. 

Die andere variante die in frage käme, ist jena ausschliesslich auf dem server zu verwenden und das model in eigene serialisierbare transportobjekte (DTO) umzufüllen, die auf die bedürfnisse vom client angepasst wären. Dann käme RMI zum einsatz.


----------



## FArt (21. Okt 2010)

borobudur hat gesagt.:


> ```
> Serialising a Model using Java serialsation will mean serialising most (if not all) of the .model.impl.* classes, and the Graph classes - eight kinds of nodes, several descendants of GraphBase, PrefixMappings, QueryHandlers, etc ad nauseum.
> ```


Das ist m.E. ein ziemlich dünnes Argument. Komplexe Strukturen kommen oft vor. Deshalb kümmert sich jede Klasse darum, wie sie serialisiert werden kann. Dann wird das relativ einfach und überschaubar... 
Nichts desto trotz: wenn du es selber machen möchtest, hast du im Prinzip das selbe Problem vor dir.... egal ob mit DTOs oder anderen Tricks...

Ich würde mal einen Blick in die Sourcen der Fremdapi werfen und einen Tag investieren, die Teile serialisierbar zu machen.... oder nimm das XML.... dann reicht auch ein einfacher Socket, ganz ohne Netty.... auch wenn es cool aussieht...


----------



## borobudur (21. Okt 2010)

FArt hat gesagt.:


> Ich würde mal einen Blick in die Sourcen der Fremdapi werfen und einen Tag investieren, die Teile serialisierbar zu machen.... oder nimm das XML.... dann reicht auch ein einfacher Socket, ganz ohne Netty.... auch wenn es cool aussieht...


In die jena-api möchte ich nicht eingreifen. Ihre serialisierungsmöglichkeit ist eben via "xml-export" resp. stream. Das passt eigentlich ganz gut zu netty.

Was ich nicht ganz verstehe bei netty, kann ich für die client-lebensdauer die channel-connection die ganze zeit offen lassen und nach belieben daten hin und her schaufeln?


----------



## Gast2 (21. Okt 2010)

borobudur hat gesagt.:


> Was ich nicht ganz verstehe bei netty, kann ich für die client-lebensdauer die channel-connection die ganze zeit offen lassen und nach belieben daten hin und her schaufeln?



Ja, kannst du machen.


----------

