Hi Alex,

Think it is ok for a first flavor (note that the scope of the server config
can be dependent since it is used once, the lookup creational context can
also be eagerly released).

In terms of impl a few notes - not required but while I'm in the code I
will mention it:

1. the startup can be async and a bean CompletionStage<HttpServerStatus>
can be added in cdi context to let the app wait for the server to be ready
if needed (or event block the startup)
2. the sync() call can be toggled by a flag in the config
3. if you handle a single server I guess a httpserver.properties can enable
to replace the config bean (or do the lookup of all httpserver instance to
start them all in afterDeploymentValidation)
4. (the only really important note) don't block CDI startup nor stop your
server just after starting it in afterDeploymentValidation - guess it is an
in progress part ;)


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 mer. 15 juil. 2020 à 14:52, Alexander Fischer <fische...@mailbox.org> a
écrit :

> 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