Trustin Lee wrote:
> On 8/17/07, Niklas Therning <[EMAIL PROTECTED]> wrote:
>   
>> Trustin Lee wrote:
>>     
>>> On 8/17/07, Maarten Bosteels <[EMAIL PROTECTED]> wrote:
>>>
>>>       
>>>> On 8/17/07, Trustin Lee <[EMAIL PROTECTED]> wrote:
>>>>
>>>>         
>>>>> On 8/17/07, Julien Vermillard <[EMAIL PROTECTED]> wrote:
>>>>>
>>>>>           
>>>>>> Hi,
>>>>>> It think the ProtocolDecoder implementer can encapsulate his logic
>>>>>> under some other class if it doesn't want to depend on MINA, but with
>>>>>> ByteBuffer, and all the point Maaarten added (like
>>>>>> ProtocolDecoderOutput) I think it won't be easly doable without
>>>>>> breaking the codec API and sacrifice some of it simplicity.
>>>>>>
>>>>>>             
>>>>> Yeah, you are right.  I forgot the ByteBuffer! :)
>>>>>
>>>>> But the point here is to decouple a codec from IoSession so the codec
>>>>> can be easily adaptable into other application component.  ByteBuffer
>>>>> and ProtocolEncoder/DecoderOutput is very easy to convert as you know
>>>>> because they are very simple, but IoSession is a different beast.
>>>>>
>>>>> We could provide a mock implementation of IoSession, but I guess it
>>>>> will not look nice (i.e. it violates OO principle).
>>>>>
>>>>>           
>>>> Ok, back to your original suggestion :-)
>>>>
>>>>         
>>> Good to see you back to the track. :D
>>>
>>>
>>>       
>>>> I think it's a really good idea to remove the IoSession from the signature
>>>> of the encoder/decoder.
>>>> Testing encoders/decoders will also be asier since  one won't need a Dummy
>>>> IoSession anymore.
>>>>
>>>>         
>>> Exactly.  That's why I posted the first message in this thread.  :)
>>> However, I wanted to make sure if there's any special use case I might
>>> have missed.
>>>
>>> Hey MINA community, your participation is appreciated!
>>>
>>> Thanks in advance,
>>> Trustin
>>>
>>>       
>> I'd say that the current ProtocolEncoder and ProtocolDecoder are fine. I
>> see no problem with having them depend on IoSession. Instead we could
>> create base classes for our codecs which aren't dependent on IoSession
>> (use Map only) and don't implement ProtocolDecoder/Encoder at all. Then
>> the actual ProtocolDecoder/Encoder implementations would simply extend
>> these base classes and call the base class with
>> IoSession.getAttributesMap() as argument (provided that there is such a
>> method, I don't remember at the moment).
>>
>> This way the codec could be even more independent from MINA. They don't
>> even implement ProtocolDecoder/Encoder and the child classes would
>> probably be trivial in most cases.
>>
>> WDYT?
>>     
>
> It sounds like an interesting idea.  We could probably provide a
> separate package that contains the classes you mentioned and
> ByteBuffer (I think we still need coupling with MINA ByteBuffer
> because it's very convenient.)
>
> Could you provide an example code of the generic codec you are
> suggesting to help our understanding?
>
> Trustin
>   
Well, consider the HttpRequestDecoder in examples. Lets break out the
methods

boolean messageComplete(ByteBuffer in)
HttpRequestMessage decodeBody(ByteBuffer in)
Map parseRequest(Reader is)

into a base class and change the methods' scope to protected:

public class BaseHttpRequestDecoder {
    private static final byte[] CONTENT_LENGTH = new
String("Content-Length:")
            .getBytes();

    private final CharsetDecoder decoder = Charset.defaultCharset()
            .newDecoder();

    protected boolean messageComplete(ByteBuffer in) { ... }
    protected HttpRequestMessage decodeBody(ByteBuffer in) { ... }
    protected Map parseRequest(Reader is) { ... }
}

The only dependency on MINA here is (I hope!) ByteBuffer.

The new HttpRequestDecoder would simply become

public class HttpRequestDecoder extends BaseHttpRequestDecoder {

    public MessageDecoderResult decodable(IoSession session, ByteBuffer
in) {
        // Return NEED_DATA if the whole header is not read yet.
        try {
            return messageComplete(in) ? MessageDecoderResult.OK
                    : MessageDecoderResult.NEED_DATA;
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return MessageDecoderResult.NOT_OK;
    }

    public MessageDecoderResult decode(IoSession session, ByteBuffer in,
            ProtocolDecoderOutput out) throws Exception {
        // Try to decode body
        HttpRequestMessage m = decodeBody(in);

        // Return NEED_DATA if the body is not fully read.
        if (m == null) {
            return MessageDecoderResult.NEED_DATA;
        }

        out.write(m);

        return MessageDecoderResult.OK;
    }

    public void finishDecode(IoSession session, ProtocolDecoderOutput out)
            throws Exception {
    }
}

I think this would work in this example at least. :-) Maybe delegation
would be better than subclassing in this case since HttpRequestDecoder
cannot extend MessageDecoderAdapter any longer.

Disclaimer: I have no idea whether this will work for any decoder/encoder.

-- 
Niklas Therning
www.spamdrain.net

Reply via email to