Hi Hubert,
>
> Hi Alexey,
>
> We had internal project in company that got open sourced: http://preon.sourceforge.net/
> Its all about binary formats, quite similar to your stuff here, it
> even has conditionals, so you can easily handle multiple versions.
> Please take a look at it, as you may avoid righting something that
> is already available.
>
> Idea of having binary data described by annotations is great.
>
> BTW Preon can also generate human readable documentation out of
> annotated class (spec).
Very interesting!
I've read briefly the presentation you have on web pages.
Currently have just 2 questions:
(1) When working with network it could happen, that ByteBuffer doesn't
have complete message or has several of them.
Does preon support such a usecase?
Cause currently I see, that Codec is able to return result object, but
what if there is not enough data for restoring whole object?
The same situation with serialization, when we pass Object and
ByteBuffer with size less, than required for serializing the Object...
So, basically, what we need (and doing currently in smart codec
implementation) - is to pass the Buffer and if it doesn't have enough
data - save the processing state in external storage (some Map let's
say), and call Codec again, once we will have next chunk of data
available.
(2) I didn't find how, but I'm pretty sure there is mechanism to
customize Codecs for certain data types, right?
Thank you!
WBR,
Alexey.
>
> HTH,
> Hubert.
>
> On Tue, Dec 16, 2008 at 2:46 PM, Oleksiy Stashok <Oleksiy.Stashok_at_sun.com
> > wrote:
> 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/
>
>
>
> --
> Hubert Iwaniuk