Hey Romain,

you can now take a look at the current state. A builder pattern is
implemented, and in the showcase you can see how the server is
configured and injected.
https://github.com/a-rekkusu/owb-centric-microserver

Please let me know what you think.

Best regards,
Alex

On 08.07.2020 16:19, Romain Manni-Bucau wrote:
> Le mer. 8 juil. 2020 à 14:42, Alexander Fischer <fische...@mailbox.org> a
> écrit :
>
>> 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?
>>
> Having a fluent API is good I think since it will often be created in a
> producer, then you can use the flavor you like.
> I tend to keep using fluent setters cause factories (xbean-finder, spring,
> etc...) handle them more easily but not sure it is required there.
>
>
>> 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)?
>>
> @Inject HttpServer server;
>
> String target = "http://localhost:"; + server.getPort(); // ensure that if
> the original port is 0 (random) then getPort returns the actual runtime port
>
> Host and if ssl is enabled are also useful info.
>
>
>> 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