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