>>>>>> public static final int PORT = 7778;
>>>>>> public void testStandaloneFilter() throws Exception {
>>>>>> Connection connection = null;
>>>>>> TCPNIOTransport transport =
>>>>>> TransportManager.instance().createTCPTransport();
>>>>>> transport.getFilterChain().add(new TransportFilter());
>>>>>> transport.getFilterChain().add(new UTFStringFilter());
>>>>>> transport.getFilterChain().add(new EchoFilter());
>>>>>
>>>>> We still need to discuss the getFilterChain() names ;-)
>>>> :) ok
>>>>>> try {
>>>>>> transport.bind(PORT);
>>>>>> transport.start();
>>>>>> ConnectFuture future =
>>>>>> transport.connectAsync("localhost", PORT);
>>>>>> connection = (TCPNIOConnection) future.get(10,
>>>>>> TimeUnit.SECONDS);
>>>>>> assertTrue(connection != null);
>>>>>> String message = "Hello world!";
>>>>>> FilterChain filterChain = transport.getFilterChain();
>>>>>> WriteResult result = filterChain.write(connection,
>>>>>> message);
>>>>>> assertEquals(result.getMessage(), message);
>>>>>> ReadResult readResult = filterChain.read(connection);
>>>>>
>>>>> OK I'm not sure about this example. It seems we first works with
>>>>> the Transport object and then switch to the FilterChain. If the
>>>>> FilterChain handler the read/write logic, why not the
>>>>> connectAsync be on the FilterChain as well?
>>>> Well, I'm not trying to move transport logic to filterchain. I'm
>>>> just showing how it's possible to use filterchain in standalone
>>>> mode.
>>>> How data could be read from the connection, pass the filterchain
>>>> and finally we will have filterchain processed message (String in
>>>> our case).
>>>
>>> That's still confusing IMO. We should really have a single point
>>> of entry.
>> But filterchain read/write should not be entry point. It's just
>> feature.
>> Which, IMHO, could be very useful for client side.
>
> I agree, but we seems to have many doors to enter the same room.
> What I'm trying to say is we should reduce the number of doors :-)
Well, I don't agree it's the same room :)) Filterchain read is just
feature, which could be especially useful for client side code.
>> On example I showed - we use the filterchain both on server and
>> client sides. But client side uses it in standalone mode.
>> It is just String example. But, if make, let's say, HttpFilter,
>> which will work with HttpMessage, it will mean client side could be
>> as simple as:
>> Future writeFuture = filterChain.writeAsync(httpMessage);
>
> Still not convinced that we need readSync/Async method. That will
> makes the API way too long (like the 1.8.x Context API...way too
> long IMO).
I'm looking at this, just as 3 sets of I/O operations:
readNow/writeNow
readAsync/writeAsync
read/write
which, IMHO, is not too much :)
>> ................
>> Future readFuture = filterChain.readAsync();
>> HttpMessage response = (HttpMessage) readFuture.get();
>> IMHO, this will make client side very easy and clear.
>
> +1 For the Future :-) -1 for the readFuture cast (or at least we
> should have a Message API).
ReadFuture is just subclass of Feature with predefined result:
ReadResult.
>>>>> Also, the connet() operations returns A Future, where read/write
>>>>> return a Read/WriteResult. Should read/write return a Future as
>>>>> well? I would propose we unify the API so any async operations
>>>>> like connect/read/write return a Future. From the Future, we can
>>>>> return a Result, which contains the requested information.
>>>>> Something like:
>>>> connectAsync is async operation, that's why it returns Future.
>>>> read/write are blocking - that's why Result.
>>>> readAsync/writeAsync operations return Future<Result>.
>>>> So, IMHO, it's we don't have unification problems :)
>>>
>>> Yes, but we should not make any difference between blocking or non
>>> blocking. That will make things complicated and a long API (like
>>> we currently have in 1.8.x). The shorter API we can have the
>>> better we will be :-)
>> Grizzly 1.x has blocking, non-blocking features implemented in
>> different places: InputReader/OutputWriter, AsyncRead/Write queues.
>
> Yes, and that doesn't means we were OK :-)
Agree :)
>> In Grizzly 2.0 I want to have these features (at least basic part
>> of it) being implemented under Connection API. Though it will be
>> still possible to use TemporarySelectorIO.read/write and AsyncRead/
>> Write queue API separately.
>
> +1, but I want it more cleaner :-)
:)
>> But for me, having common IO features under single interface (like
>> Connection) looks easier.
>>>>> Result result = ConnectFuture.get()
>>>>> Connection connection = result.getResult()
>>>>>
>>>>> or
>>>>>
>>>>> Connection connection = ConnectionFuture.get(..) //No cast needed
>>>> that casting was redundant. Fixed.
>>>>>
>>>>> ReadResult result = ReadFuture.get();
>>>>> WriteResult resukt = WriteFuture.get();
>>>>>
>>>>> So your example seems to "suffer" 2 issues:
>>>>>
>>>>> + Need one single Object to interact with.
>>>> transport logic is inside Connection. And FilterChain just brings
>>>> processing logic.
>>>> The connection.read() in our example will return ByteBuffer, but
>>>> filterchain.read() will return String (as result of
>>>> UTFStringFilter).
>>>
>>> Hum...I need to look at it more. I'm not sure as how can you know
>>> which filter will return what? Meaning something like:
>>>
>>> transport.getFilterChain().add(new TransportFilter());
>>> transport.getFilterChain().add(new UTFStringFilter());
>>> transport.getFilterChain().add(new LogFilter());
>>> transport.getFilterChain().add(new EchoFilter());
>>>
>>> How can I predict that readResult.getMessage() is coming from
>>> which Filter?
>> The filterchain.read() processes the chain in regular manner from
>> the first to the last. And the result message will be returned.
>> In your example, just UTFStringFilter makes some message
>> transformation, looks like other filters will just process the
>> message (not transform). So String will be returned.
>> Example like this:
>> transport.getFilterChain().add(new TransportFilter());
>> transport.getFilterChain().add(new SSLFilter());
>> transport.getFilterChain().add(new LogFilter());
>> transport.getFilterChain().add(new EchoFilter());
>> ByteBuffer message = (ByteBuffer) filterChain.read().getMessage();
>> will return ByteBuffer, the result of SSLFilter decoding. This way
>> we can implement SSL clients.
>
>
> But how can the client knows that? How can I change my mind and
> instead get the LogFilter results instead of SSLFilter result?
Well, you build the FilterChain... you should know :)
Usually the filter chain represents some ecoding/decoding + processing
logics. And usually one single Filter implements either encoding/
decoding or processing logic.
In your example encoding/decoding is implemented by: SSLFilter. Other
filters represent some processing logic: logging, echoing.
The standalone filterchain read/write reuses just encoding/decoding
logic of filterchain, which IMHO, could be very interesting
(especially for the client side).
Example I showed above with HttpMessage looks interesting, doesn't
it? :)
This way Grizzly HTTP client implementation could be very clear and
easy.
>> the following example:
>> transport.getFilterChain().add(new TransportFilter());
>> transport.getFilterChain().add(new SSLFilter());
>> transport.getFilterChain().add(new HttpFilter());
>> transport.getFilterChain().add(new LogFilter());
>> transport.getFilterChain().add(new EchoFilter());
>> HttpMessage message = (HttpMessage) filterChain.read().getMessage();
>> will return HttpMessage, the result of HttpFilter, which is invoked
>> after SSLFilter. And you see how we can implement HTTPS client.
>>> [Small thing] -> ReadResult should know what will be returned by
>>> doing getMessage(), hence no need to cast IMO.
>> In general not. But it's possible to customize the message type
>> using ReadResult generics. ReadResult<HttpMessage, SocketAddress>
>
> +1
>
>>>>> + Unify API for async operations.
>>>> it's not problem :)
>>>>>> String responseMessage = (String)
>>>>>> readResult.getMessage();
>>>>>> assertEquals(message, responseMessage);
>>>>>> } finally {
>>>>>> if (connection != null) {
>>>>>> connection.close();
>>>>>> }
>>>>>> transport.stop();
>>>>>> TransportManager.instance().close();
>>>>>
>>>>> I still find it dangerous to have 2 operations to execute
>>>>> here :-) But maybe it is only me :-)
>>>> No, no, you may be right. Just didn't time to revisit this.
>>>
>>> I think we should start filling issue on 2.0 to not loose track.
>>> So far we are only two discussing, but when every body is up to
>>> speed we will loose content :-). What do you think?
>> I agree! :)
>
> OK let's agree first and I will file after :-)
Sure :)
Thank you for feedback!
WBR,
Alexey.
>
>
> Great work so far!
>
> A+
>
> -- Jeanfranncois
>
>
>> Thanks.
>> WBR,
>> Alexey.
>>>
>>>
>>> A+
>>>
>>> -- Jeanfrancois
>>>
>>>
>>>> Thanks!
>>>> WBR,
>>>> Alexey.
>>>>>
>>>>>
>>>>> A+
>>>>>
>>>>> -- Jeanfrancois
>>>>>
>>>>>
>>>>>
>>>>>> }
>>>>>> }
>>>>>> }
>>>>>> ---------------------------------------------------------------------
>>>>>> To unsubscribe, e-mail: dev-unsubscribe_at_grizzly.dev.java.net
>>>>>> For additional commands, e-mail: dev-help_at_grizzly.dev.java.net
>>>>>
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: dev-unsubscribe_at_grizzly.dev.java.net
>>>>> For additional commands, e-mail: dev-help_at_grizzly.dev.java.net
>>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: dev-unsubscribe_at_grizzly.dev.java.net
>>>> For additional commands, e-mail: dev-help_at_grizzly.dev.java.net
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: dev-unsubscribe_at_grizzly.dev.java.net
>>> For additional commands, e-mail: dev-help_at_grizzly.dev.java.net
>>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: dev-unsubscribe_at_grizzly.dev.java.net
>> For additional commands, e-mail: dev-help_at_grizzly.dev.java.net
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe_at_grizzly.dev.java.net
> For additional commands, e-mail: dev-help_at_grizzly.dev.java.net
>