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