Hi Romain,

thanks for the feedback. I made subtasks in Jira for the leftover server
features and marked them for later.
Regarding the configuration of our server, I took a look at how
Meecrowave's Builder does it. Do you think it's a good idea to adopt
this structure or should we build it another way?
And about the server as injectable bean: can you elaborate a bit about
how you intend to use it and how it would be an advantage for you? What
methods would you need available? Would it be like a container class
that should contain all application scoped info (e.g. our HttpHandlers,
the actual server)?

Thanks and best regards,
Alex

On 06.07.2020 17:36, Romain Manni-Bucau wrote:
> Hi Alex,
>
> A completionstage is just a promise so how it is wired is not that
> important - it is not rare i don't use the fluent API for example but a
> custom listener impl - but it is key to know in which thread context is it
> executed.
> Typically with your impl you inherit the caller threading - which can be
> what you want or not. Concretely, while it is NOT netty NIOLoop threads it
> is ok I think.
> A small issue you can hit is the full http response is not chunking
> compatible but it can be done in a second phase I guess.
> In terms of global arch, you will also want to preresolve (see it as a
> precompile phase) the execution (so no CDI.current().select(info.clazz).
> get() at runtime but a resolve during the bootstrap or lazily but only
> once). Same kind of side note for query params and form params, you likely
> want to parse them lazily and call the decoder.destroy() in a finally block
> ;).
> That said, the showcase is already nice and this is pretty much details
> since the structure is there and I guess it can be tackled after GSoC.
>
> Romain Manni-Bucau
> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
> <https://rmannibucau.metawerx.net/> | Old Blog
> <http://rmannibucau.wordpress.com> | Github <https://github.com/rmannibucau> |
> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
> <https://www.packtpub.com/application-development/java-ee-8-high-performance>
>
>
> Le lun. 6 juil. 2020 à 17:03, Alexander Fischer <fische...@mailbox.org> a
> écrit :
>
>> Hey Romain,
>>
>> the API, Netty and CDI are roughly working together now.
>> How do you think we should handle the CompletionStage case in Netty?
>> Should we handle it in Netty's ChannelFuture features or leave it out of
>> there as CompletionStage does its work already?
>> Right now I went with using ChannelFuture for CompletionStage. You can
>> see the part here:
>>
>>
>> https://github.com/a-rekkusu/owb-centric-microserver/blob/master/impl/src/main/java/org/apache/peeco/impl/HttpServerHandler.java#L69
>>
>> Please let me know what you think overall. Next up would be the
>> configuration tasks (e.g. server as CDI bean).
>> Regarding the schedule, GSOC is running until August 31st, so Thomas and
>> I try to get started with the native part from next week onwards, as we
>> slowly hit the middle of the project time.
>>
>> Best regards,
>> Alex
>>
>> On 19.06.2020 16:49, Romain Manni-Bucau wrote:
>>> Except Response.setOutput which should use a plain InputStream (instead
>> of
>>> byte array flavor) it looks ok
>>>
>>> About parameters, one option is to do a "return
>>> Stream.concat(body.entrySet().stream(),
>>> form.entrySet().stream()).collect(toMap(Map.Entry::getKey,
>>> Map.Entry::getValue, this::myMerger);" but impl is a detail for now ;).
>>> Another - once again not blocking to impl - small note is you rarely use
>>> body + param in the same request so it can be lazily instantiated (avoids
>>> the parsing - netty has the needed classes to parse them) so a Supplier
>> can
>>> makes sense too, but this would be in the optim phase.
>>>
>>> In other words I think you can do a first impl with that API, then see
>> how
>>> to handle chunking and then only optimize the api internals, at least it
>> is
>>> how I would proceed.
>>>
>>> Romain Manni-Bucau
>>> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
>>> <https://rmannibucau.metawerx.net/> | Old Blog
>>> <http://rmannibucau.wordpress.com> | Github <
>> https://github.com/rmannibucau> |
>>> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
>>> <
>> https://www.packtpub.com/application-development/java-ee-8-high-performance
>>>
>>>
>>> Le ven. 19 juin 2020 à 15:53, Alexander Fischer <fische...@mailbox.org>
>> a
>>> écrit :
>>>
>>>> Hi Romain,
>>>>
>>>> you are right with your points and I've tried to apply them. The
>>>> Request.parameters() method might be solvable more elegantly. Only
>>>> streams were a bit unclear to me, but I did it as I understood it for
>>>> now (correct me if I got it wrong):
>>>> the user writes/casts his intended output to a ByteArrayInputStream,
>>>> which is handed over to netty that transforms it to its actual output
>>>> (maybe ChannelBufferOutputStream, but I have yet to figure it out).
>>>> Let me know what you think of the current state, please. Once again the
>>>> repo link, just for convenience.
>>>> https://github.com/a-rekkusu/owb-centric-microserver
>>>>
>>>> Thanks and best regards,
>>>> Alex
>>>>
>>>> On 18.06.2020 15:26, Romain Manni-Bucau wrote:
>>>>> Should matching be an array? If so how would you impl it? (it is
>>>> associated
>>>>> with "url" or another parameter for its config, for instance EXACT +
>> path
>>>>> so i don't see how it would work to support EXACT and WILDCARD at the
>>>> same
>>>>> time for ex).
>>>>> In Request ensure to return Map<String, List<String>> and not
>>>>> HashMap<String, String> (it is not a hashmap cause headers are case
>>>>> insensitive for ex, a TreeMap(String.CASE_INSENSITIVE) is better IMHO
>> but
>>>>> no need to expose the impl).
>>>>> Parameters should likely be split in body parameters (form data) and
>>>> query
>>>>> parameters (so getParameter(String) would be a facade to 2 get in query
>>>> and
>>>>> form maps).
>>>>> Kind of the same remark on the response (for HashMap) + payload is an
>>>>> InputStream. This one requires some explanation:
>>>>>
>>>>> 1. Using a ByteArrayOutputStream is quite limiting since you drop all
>>>>> decorations and oversized payload support
>>>>> 2. An outputstream requires the server to know how to map this object
>> to
>>>>> something readable (input stream or the reactive equivalent)
>>>>> 3. output stream will likely require the server to inject the instance
>>>> once
>>>>> 1 is fixed which is something we should try to avoid
>>>>>
>>>>> Now if you move to an Inputstream you can consumer it easily from the
>>>>> server point of view, wrap it easily (in a filter for ex) and setting
>> the
>>>>> output is as easy:
>>>>>
>>>>> setOutput(new ByteArrayInputStream(...));
>>>>> + the user friendly flavor(s): setOutput(String) (which does the
>>>>> setoutput(inputStream) + setHeader(content-length))
>>>>>
>>>>> Romain Manni-Bucau
>>>>> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
>>>>> <https://rmannibucau.metawerx.net/> | Old Blog
>>>>> <http://rmannibucau.wordpress.com> | Github <
>>>> https://github.com/rmannibucau> |
>>>>> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
>>>>> <
>> https://www.packtpub.com/application-development/java-ee-8-high-performance
>>>>>
>>>>> Le jeu. 18 juin 2020 à 14:58, Alexander Fischer <fische...@mailbox.org
>>>> a
>>>>> écrit :
>>>>>
>>>>>> Hey Romain,
>>>>>>
>>>>>> thanks for the feedback! I have implemented the API feedback now,
>> please
>>>>>> take another look:
>>>>>> https://github.com/a-rekkusu/owb-centric-microserver
>>>>>>
>>>>>> Are there functionalities that you miss?
>>>>>> Else, the Netty implementation ist next.
>>>>>>
>>>>>> Best regards,
>>>>>> Alex
>>>>>>
>>>>>> On 16.06.2020 14:04, Romain Manni-Bucau wrote:
>>>>>>> Hi Alex,
>>>>>>>
>>>>>>> I don't think you need the HttpHandler annotation to be a qualifier
>>>> (will
>>>>>>> typically end up on a method not producing any bean at some point I
>>>> think
>>>>>>> as in the example at the end of this answer).
>>>>>>> I guess Request/Response models are not yet done? Side note before
>> you
>>>>>> work
>>>>>>> on them: maybe don't copy servlet API, content-type, content-length
>> etc
>>>>>> are
>>>>>>> just headers, no need to make them specific, also prefer to set the
>>>>>> payload
>>>>>>> (as an inputstream or reactive stream) rather than encapsulating
>>>>>> read/write
>>>>>>> methods, it enables a better composition and decoration in general
>> and
>>>>>>> bypasses to go through a provider/factory to create
>> requests/responses.
>>>>>>> Last thing is you probably want to create a package for that work and
>>>> not
>>>>>>> use the default one ;).
>>>>>>>
>>>>>>> Typically it is a good start IMHO and once this works I'd do another
>>>>>> small
>>>>>>> iteration to end up on:
>>>>>>>
>>>>>>> public class HelloWorldHandlerFuture
>>>>>>> {
>>>>>>> @HttpHandler(method = {HttpMethod.GET, HttpMethod.POST}, url =
>>>> "/hello",
>>>>>>> matching = Matching.EXACT)
>>>>>>> public CompletionStage<Response> apply(Request request)
>>>>>>> {
>>>>>>> return CompletableFuture.supplyAsync(() ->
>>>>>>> {
>>>>>>> Response response = new Response();
>>>>>>> response.setStatus(200);
>>>>>>> response.write("Hello World from " + getClass().getName());
>>>>>>> return response;
>>>>>>> });
>>>>>>> }
>>>>>>> }
>>>>>>>
>>>>>>> Small side note (fully related to CompletionStage more than your
>>>> current
>>>>>>> work: if you want a synchronous impl of a CompletionStage you can use
>>>>>>> CompletionFuture.completedFuture(response) - avoid the sypplyAsync -
>>>> and
>>>>>> if
>>>>>>> you want to be async (sypplyAsync) ensure you pass an executor as
>>>> second
>>>>>>> parameter otherwise you end up being in default ForkJoinPool which
>> has
>>>> a
>>>>>>> lot of side effects and limitations.
>>>>>>>
>>>>>>> Anyway, very good first iteration, it is pretty close to what I was
>>>>>>> envisioning and it looks as smooth as I was thinking.
>>>>>>>
>>>>>>> Small tip for the impl phase (don't know if it is the next one or
>> not):
>>>>>> for
>>>>>>> the handler registration, ensure to enable to do it programmatically:
>>>>>>> register(Function<Request, CompletionStage<Response>>). It will
>> enable
>>>> to
>>>>>>> use other models than the annotated one which is just a simplified
>> API
>>>> of
>>>>>>> the actual one the server uses internally.
>>>>>>>
>>>>>>> Romain Manni-Bucau
>>>>>>> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
>>>>>>> <https://rmannibucau.metawerx.net/> | Old Blog
>>>>>>> <http://rmannibucau.wordpress.com> | Github <
>>>>>> https://github.com/rmannibucau> |
>>>>>>> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
>>>>>>> <
>> https://www.packtpub.com/application-development/java-ee-8-high-performance
>>>>>>> Le mar. 16 juin 2020 à 13:08, Alexander Fischer <
>> fische...@mailbox.org
>>>>>> a
>>>>>>> écrit :
>>>>>>>
>>>>>>>> Hi Romain,
>>>>>>>>
>>>>>>>> I have made a first draft for the API and example showcase:
>>>>>>>> https://github.com/a-rekkusu/owb-centric-microserver
>>>>>>>>
>>>>>>>> Please take a look and let me know what you think.
>>>>>>>> CompletionStage is supported, but right now for all requests on a
>>>>>>>> handler. If you would want a CompletableFuture only for POST for
>>>>>>>> example, and not on GET, how do you think we should handle that?
>>>>>>>> We could do it with a second HttpHandler on the same url but with
>> the
>>>>>>>> respective HttpMethod (e. g. HelloWorldHandlerGet /
>>>>>> HelloWorldHandlerPost).
>>>>>>>> Kind regards,
>>>>>>>> Alex
>>>>>>>>
>>>>>>>> On 06.06.2020 15:44, Romain Manni-Bucau wrote:
>>>>>>>>> Hi Alex,
>>>>>>>>>
>>>>>>>>> Nothing is written in the stone but here is how I would approach
>>>> that:
>>>>>>>>> 1. Write a HTTP server able to call a handler to answer a request -
>>>> you
>>>>>>>> can
>>>>>>>>> start by giving a hardcoded handler but in terms of design, ensure
>>>> you
>>>>>>>> get
>>>>>>>>> something taking a Request abstracting as input and a Response
>>>>>>>> abstraction
>>>>>>>>> as output.
>>>>>>>>> Netty has these abstraction but we don't want to depend on netty so
>>>> you
>>>>>>>>> should duplicate it making it even more user friendly (netty stays
>>>> low
>>>>>>>>> level).
>>>>>>>>> 2. Make this server CDI friendly, basically a CDI bean and nice to
>>>>>> have,
>>>>>>>>> configurable (port, ssl, ...) with MP-Config (or equivalent - if
>> you
>>>>>>>> take a
>>>>>>>>> Map<String, String> as input you won here),
>>>>>>>>> 3. Now you have to abstract the handler and make the default
>> handler
>>>> a
>>>>>>>>> facade for user handlers. User handlers are CDI beans. I would
>> start
>>>> by
>>>>>>>>> making them with something between servlet and jaxrs:
>>>>>>>>>
>>>>>>>>> @HttpHandler(method = {GET, POST}, url = "/foo", mathing =
>>>>>>>> Matching.EXACT)
>>>>>>>>> method being the http method handled, url the urlpattern matched
>>>> thanks
>>>>>>>> the
>>>>>>>>> matching algo (i used an enum but it can be anything equivalent).
>>>> EXACT
>>>>>>>>> means request path == url, we can envision wildcard matching (as in
>>>>>>>>> servlet), regex matching etc...
>>>>>>>>>
>>>>>>>>> The signature can start to be the exact expected one
>>>>>>>>> (CompletionStage<Response> onRequest(Request)) while validated in
>> the
>>>>>> cdi
>>>>>>>>> extension grabbing the handlers, then you can relax the
>>>> CompletionStage
>>>>>>>>> requirement (Response onReq(Request)) and finally you can go closer
>>>> to
>>>>>>>>> jaxrs adding @PathParam/@QueryParam/... like annotations but if
>>>> Request
>>>>>>>> API
>>>>>>>>> is nice enough it is not required in this layer - it can be a layer
>>>> on
>>>>>>>> top
>>>>>>>>> as jaxrs is on top of servlet. What's important here is to be
>>>> reactive
>>>>>>>>> friendly by design - I'll let you play with the threading
>> strategies
>>>> to
>>>>>>>>> have an useful CompletionStage and how to link it - or not ;) - to
>>>>>> netty
>>>>>>>>> executors.
>>>>>>>>>
>>>>>>>>> Once handlers well done, it is easy to add filters on top of it,
>> same
>>>>>>>> kind
>>>>>>>>> of API but it takes another optional parameter:
>>>>>>>>>
>>>>>>>>> CompletionStage<Response> onRequest(Request request,
>>>>>>>>> Supplier<CompletionStage<Response>> proceed);
>>>>>>>>>
>>>>>>>>> with proceed the call to filter N+1 and finally the handler (check
>>>> out
>>>>>>>> OWB
>>>>>>>>> interceptor impl, it is exactly the same.
>>>>>>>>>
>>>>>>>>> Last important point: ensure to handle @Priority (or add priority =
>>>> int
>>>>>>>>> in @HttpHandler) cause when you will implement the matching chain
>> you
>>>>>>>> will
>>>>>>>>> need an order normally.
>>>>>>>>>
>>>>>>>>> Bonus: you can make the matching strategies pluggable if you want
>> and
>>>>>>>> just
>>>>>>>>> provide some defaults OOTB.
>>>>>>>>>
>>>>>>>>> Hope it makes sense.
>>>>>>>>>
>>>>>>>>> Romain Manni-Bucau
>>>>>>>>> @rmannibucau <https://twitter.com/rmannibucau> |  Blog
>>>>>>>>> <https://rmannibucau.metawerx.net/> | Old Blog
>>>>>>>>> <http://rmannibucau.wordpress.com> | Github <
>>>>>>>> https://github.com/rmannibucau> |
>>>>>>>>> LinkedIn <https://www.linkedin.com/in/rmannibucau> | Book
>>>>>>>>> <
>> https://www.packtpub.com/application-development/java-ee-8-high-performance
>>>>>>>>> Le jeu. 4 juin 2020 à 15:35, Alexander Fischer <
>>>> fische...@mailbox.org>
>>>>>> a
>>>>>>>>> écrit :
>>>>>>>>>
>>>>>>>>>> Hello everyone,
>>>>>>>>>>
>>>>>>>>>> in the last month I have spent most of my time getting to know
>>>> coding
>>>>>>>>>> basics of Maven, Netty, CDI/OWB and Servlets/Tomcat. I got to know
>>>> CDI
>>>>>>>>>> extensions which will be the technological foundation for the
>>>> server.
>>>>>>>>>> Next up will be defining and implementing the HTTP API, which will
>>>>>> bring
>>>>>>>>>> CDI and Netty together. Feel free to contribute your thoughts on
>> the
>>>>>>>>>> matter here on the mailing list or in the respective Jira issue:
>>>>>>>>>> https://issues.apache.org/jira/projects/OWB/issues/OWB-1319
>>>>>>>>>>
>>>>>>>>>> @Romain: can you share some ideas, annotations, interfaces for how
>>>> you
>>>>>>>>>> see the API roughly? Any kind of formal requirement-proposal would
>>>> be
>>>>>>>>>> helpful to start with.
>>>>>>>>>>
>>>>>>>>>> Thanks and best regards,
>>>>>>>>>> Alexander
>>>>>>>>>>
>>>>>>>>>>

Reply via email to