dev@grizzly.java.net

Re: Grizzly 2.0: Smart codec

From: Oleksiy Stashok <Oleksiy.Stashok_at_Sun.COM>
Date: Wed, 17 Dec 2008 12:13:57 +0100

Hi John,


> Great I think it real is a time saver!
> Just one question I love to have
>
> private int bodyLength;
>
> @Sequence(
> size=_at_Size(ref="bodyLength"),
> limit=_at_Limit(8192)
> )
> private BufferWrapper buffer;
>
> and have buffer be a sliced view on Grizzly's current Buffer used to
> read in bytes.
> (Of course without the allready decoded bytes)
>
> Would that be easy to implement?

I had the same idea, because want to avoid copying all the time.
Though it may not work in several cases.

Let's say we have ByteBufferWrapperDecoder, which does, what you
propose we call it like:

TransformationResult<Buffer> result =
byteBufferWrapperDecoder.transform(incomingBuffer);
Buffer decodedBuffer = result.getResult();

It looks fine...
But what if there are further elements in object to be decoded, and we
figured out, that incomingBuffer doesn't have enough data to decode
them all. It means we will need to release incomingBuffer and wait the
rest of data. Releasing incomingBuffer will make decodedBuffer invalid.

So, basically, the case you're proposing will work fine only in
situations, where BufferWrapper is the last element in to be decoded.

For sure I could be wrong... what do you think?

Thanks.

WBR,
Alexey.


>
>
>
>
>
>
> -------- Original-Nachricht --------
>> Datum: Tue, 16 Dec 2008 14:46:07 +0100
>> Von: Oleksiy Stashok <Oleksiy.Stashok_at_Sun.COM>
>> An: dev_at_grizzly.dev.java.net
>> Betreff: Grizzly 2.0: Smart codec
>
>> Hi,
>>
>> I'd like to receive some feedback on feature we've just added to
>> Grizzly 2.0 workspace, named smart codec (smart filter or smart
>> transformer) :)
>> I called it "smart", because using this codec we don't need to write
>> any parsers for custom messages. The codec analyzes class structure
>> and performs encoding/decoding according to the type structure. There
>> are some annotations, which could be used in order to change the
>> default transformation logic.
>>
>> How it looks like?
>>
>> 1) First of all we define our custom message class. As example I'll
>> take GIOP message:
>>
>> public class GIOPMessage {
>> private byte G;
>> private byte I;
>> private byte O;
>> private byte P;
>>
>> private byte major;
>> private byte minor;
>>
>> private byte flags;
>> private byte value;
>>
>> private int bodyLength;
>>
>> @Sequence(
>> size=_at_Size(ref="bodyLength"),
>> limit=_at_Limit(8192)
>> )
>> private byte[] body;
>>
>> public GIOPMessage() {
>> }
>>
>> public GIOPMessage(byte major, byte minor,
>> byte flags, byte value, byte[] body) {
>> G = 'G';
>> I = 'I';
>> O = 'O';
>> P = 'P';
>>
>> this.major = major;
>> this.minor = minor;
>> this.flags = flags;
>> this.value = value;
>>
>> bodyLength = body.length;
>> this.body = body;
>> }
>> }
>>
>> GIOP message contains of header (12 bytes) and body.
>> The interesting part here, is how we define body byte array. We use
>> annotation @Sequence, and define, that body length is located in
>> "bodyLength" field of the same object, and maximum body size is 8192.
>>
>> 2) Server part....
>>
>> // Create TCP NIO transport
>> TCPNIOTransport transport =
>> TransportFactory.getInstance().createTCPTransport();
>>
>> // Initialize smart Codec
>> SmartCodec smartCodec = new SmartCodec(GIOPMessage.class);
>>
>> // Add filters to the chain
>> transport.getFilterChain().add(new TransportFilter());
>> transport.getFilterChain().add(new SmartFilter(smartCodec));
>>
>> // GIOPProcessorFilter works with GIOPMessage, not with Buffers
>> transport.getFilterChain().add(new GIOPProcessorFilter());
>>
>>
>> try {
>> // Bind server socket and start transport
>> transport.bind(PORT);
>> transport.start();
>>
>> System.out.println("Press <enter> to exit...");
>> System.in.read();
>> } finally {
>> transport.stop();
>> TransportFactory.getInstance().close();
>> }
>> }
>>
>> That's it. So, your work will be just write GIOPProcessorFilter,
>> which
>> knows what to do with GIOP message, and don't bother with possible
>> packet fragmentation, ByteBuffers or other things.
>>
>> 3) Client part....
>>
>> Connection connection = null;
>> // Create TCP NIO transport
>> TCPNIOTransport transport =
>> TransportFactory.getInstance().createTCPTransport();
>>
>> // Initialize smart Codec
>> SmartCodec smartCodec = new SmartCodec(GIOPMessage.class);
>>
>> try {
>> // start transport
>> transport.start();
>>
>> // Connect client to the GIOP server
>> ConnectFuture future = transport.connect(GIOPServer.HOST,
>> GIOPServer.PORT);
>>
>> connection = future.get(10, TimeUnit.SECONDS);
>>
>> // Enable standalone mode for this connection
>> // (don't use Filter chains or other I/O event
>> processors)
>> connection.setPreferableProcessorSelector(new
>> NullProcessorSelector());
>>
>> // Initialize sample GIOP message
>> byte[] testMessage = new String("GIOP test").getBytes();
>> GIOPMessage sentMessage = new GIOPMessage((byte) 1,
>> (byte) 2,
>> (byte) 0x0F, (byte) 0, testMessage);
>>
>> // Write message
>> Future<WriteResult> writeFuture =
>> connection.write(sentMessage,
>> smartCodec.getEncoder());
>>
>> writeFuture.get(10, TimeUnit.SECONDS);
>>
>> .....................................................................
>>
>> // Receive result back
>> Future<ReadResult> readFuture = connection.read(null,
>> smartCodec.getDecoder());
>> ReadResult result = readFuture.get(10, TimeUnit.SECONDS);
>> GIOPMessage reply = (GIOPMessage) result.getMessage();
>> .....................................
>>
>> Here [1] you can find working code of simple GIOP client and GIOP
>> echo
>> server.
>>
>> Smart codec is able to work with complex message types, which have
>> not
>> just primitives in it. For example:
>> public class MyMessage {
>> MessageHeader header;
>> MessageBody body;
>> }
>>
>> public class MessageHeader {
>> private int id;
>> private int seq;
>> }
>>
>> public class MessageBody {
>> private int length;
>> @Sequence(size=_at_Size(ref="length"))
>> private byte[] body;
>> }
>>
>>
>> If you have some message, or message member, which encoding/decoding
>> you want to customize, you can set the custom Transformer, which will
>> be responsible for encoding it.
>>
>> public class CustomizedMessage {
>> @Encoder("my.own.header.Encoder")
>> @Decoder("my.own.header,Decoder")
>> CustomizedHeader header;
>>
>> NonCustomizedBody body;
>> }
>>
>> Will appreciate your feedback!
>>
>> Thanks.
>>
>> WBR,
>> Alexey.
>>
>>
>> [1]
>> https://grizzly.dev.java.net/source/browse/grizzly/branches/2dot0/samples/framework-samples/src/main/java/org/glassfish/grizzly/samples/smart/giop/
>
> --
> Psssst! Schon vom neuen GMX MultiMessenger gehört? Der kann`s mit
> allen: http://www.gmx.net/de/go/multimessenger
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe_at_grizzly.dev.java.net
> For additional commands, e-mail: dev-help_at_grizzly.dev.java.net
>