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 > >>>>>> > >>>>>> >